sensu-plugins-elasticsearch-boutetnico 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/CHANGELOG.md +1 -0
 - data/LICENSE +22 -0
 - data/README.md +60 -0
 - data/bin/check-es-circuit-breakers.rb +151 -0
 - data/bin/check-es-cluster-health.rb +132 -0
 - data/bin/check-es-cluster-status.rb +177 -0
 - data/bin/check-es-file-descriptors.rb +173 -0
 - data/bin/check-es-heap.rb +205 -0
 - data/bin/check-es-indexes.rb +89 -0
 - data/bin/check-es-indices-field-count.rb +194 -0
 - data/bin/check-es-indices-sizes.rb +199 -0
 - data/bin/check-es-node-status.rb +137 -0
 - data/bin/check-es-query-average.rb +287 -0
 - data/bin/check-es-query-count.rb +275 -0
 - data/bin/check-es-query-exists.rb +205 -0
 - data/bin/check-es-query-ratio.rb +306 -0
 - data/bin/check-es-shard-allocation-status.rb +143 -0
 - data/bin/handler-es-delete-indices.rb +99 -0
 - data/bin/metrics-es-cluster.rb +215 -0
 - data/bin/metrics-es-node-graphite.rb +354 -0
 - data/bin/metrics-es-node.rb +143 -0
 - data/lib/sensu-plugins-elasticsearch.rb +3 -0
 - data/lib/sensu-plugins-elasticsearch/elasticsearch-common.rb +63 -0
 - data/lib/sensu-plugins-elasticsearch/elasticsearch-query.rb +153 -0
 - data/lib/sensu-plugins-elasticsearch/version.rb +9 -0
 - metadata +351 -0
 
| 
         @@ -0,0 +1,143 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #! /usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Checks ElasticSearch shard allocation setting status
         
     | 
| 
      
 4 
     | 
    
         
            +
            # ===
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # DESCRIPTION:
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   Checks the ElasticSearch shard allocation persistent and transient settings
         
     | 
| 
      
 8 
     | 
    
         
            +
            #   and will return status based on a difference in those settings.
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # OUTPUT:
         
     | 
| 
      
 11 
     | 
    
         
            +
            #   plain-text
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # PLATFORMS:
         
     | 
| 
      
 14 
     | 
    
         
            +
            #   Linux
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
            # DEPENDENCIES:
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   gem: sensu-plugin
         
     | 
| 
      
 18 
     | 
    
         
            +
            #   gem: rest-client
         
     | 
| 
      
 19 
     | 
    
         
            +
            #
         
     | 
| 
      
 20 
     | 
    
         
            +
            # USAGE:
         
     | 
| 
      
 21 
     | 
    
         
            +
            #
         
     | 
| 
      
 22 
     | 
    
         
            +
            # NOTES:
         
     | 
| 
      
 23 
     | 
    
         
            +
            #
         
     | 
| 
      
 24 
     | 
    
         
            +
            # LICENSE:
         
     | 
| 
      
 25 
     | 
    
         
            +
            #   Copyright 2014 Yieldbot, Inc  <devops@yieldbot.com>
         
     | 
| 
      
 26 
     | 
    
         
            +
            #   Released under the same terms as Sensu (the MIT license); see LICENSE
         
     | 
| 
      
 27 
     | 
    
         
            +
            #   for details.
         
     | 
| 
      
 28 
     | 
    
         
            +
            #
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            require 'sensu-plugin/check/cli'
         
     | 
| 
      
 31 
     | 
    
         
            +
            require 'rest-client'
         
     | 
| 
      
 32 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 33 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            #
         
     | 
| 
      
 36 
     | 
    
         
            +
            # == Elastic Search Shard Allocation Status
         
     | 
| 
      
 37 
     | 
    
         
            +
            #
         
     | 
| 
      
 38 
     | 
    
         
            +
            class ESShardAllocationStatus < Sensu::Plugin::Check::CLI
         
     | 
| 
      
 39 
     | 
    
         
            +
              option :scheme,
         
     | 
| 
      
 40 
     | 
    
         
            +
                     description: 'URI scheme',
         
     | 
| 
      
 41 
     | 
    
         
            +
                     long: '--scheme SCHEME',
         
     | 
| 
      
 42 
     | 
    
         
            +
                     default: 'http'
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              option :server,
         
     | 
| 
      
 45 
     | 
    
         
            +
                     description: 'Elasticsearch server',
         
     | 
| 
      
 46 
     | 
    
         
            +
                     short: '-s SERVER',
         
     | 
| 
      
 47 
     | 
    
         
            +
                     long: '--server SERVER',
         
     | 
| 
      
 48 
     | 
    
         
            +
                     default: 'localhost'
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              option :port,
         
     | 
| 
      
 51 
     | 
    
         
            +
                     description: 'Port',
         
     | 
| 
      
 52 
     | 
    
         
            +
                     short: '-p PORT',
         
     | 
| 
      
 53 
     | 
    
         
            +
                     long: '--port PORT',
         
     | 
| 
      
 54 
     | 
    
         
            +
                     default: '9200'
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              option :allow_non_master,
         
     | 
| 
      
 57 
     | 
    
         
            +
                     description: 'Allow check to run on non-master nodes',
         
     | 
| 
      
 58 
     | 
    
         
            +
                     short: '-a',
         
     | 
| 
      
 59 
     | 
    
         
            +
                     long: '--allow-non-master',
         
     | 
| 
      
 60 
     | 
    
         
            +
                     default: false
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              option :timeout,
         
     | 
| 
      
 63 
     | 
    
         
            +
                     description: 'Sets the connection timeout for REST client',
         
     | 
| 
      
 64 
     | 
    
         
            +
                     short: '-t SECS',
         
     | 
| 
      
 65 
     | 
    
         
            +
                     long: '--timeout SECS',
         
     | 
| 
      
 66 
     | 
    
         
            +
                     proc: proc(&:to_i),
         
     | 
| 
      
 67 
     | 
    
         
            +
                     default: 45
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              option :user,
         
     | 
| 
      
 70 
     | 
    
         
            +
                     description: 'Elasticsearch User',
         
     | 
| 
      
 71 
     | 
    
         
            +
                     short: '-u USER',
         
     | 
| 
      
 72 
     | 
    
         
            +
                     long: '--user USER'
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              option :password,
         
     | 
| 
      
 75 
     | 
    
         
            +
                     description: 'Elasticsearch Password',
         
     | 
| 
      
 76 
     | 
    
         
            +
                     short: '-P PASS',
         
     | 
| 
      
 77 
     | 
    
         
            +
                     long: '--password PASS'
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              option :cert_file,
         
     | 
| 
      
 80 
     | 
    
         
            +
                     description: 'Cert file to use',
         
     | 
| 
      
 81 
     | 
    
         
            +
                     long: '--cert-file CERT'
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              def get_es_resource(resource)
         
     | 
| 
      
 84 
     | 
    
         
            +
                headers = {}
         
     | 
| 
      
 85 
     | 
    
         
            +
                if config[:user] && config[:password]
         
     | 
| 
      
 86 
     | 
    
         
            +
                  auth = 'Basic ' + Base64.strict_encode64("#{config[:user]}:#{config[:password]}").chomp
         
     | 
| 
      
 87 
     | 
    
         
            +
                  headers = { 'Authorization' => auth }
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                r = if config[:cert_file]
         
     | 
| 
      
 91 
     | 
    
         
            +
                      RestClient::Resource.new("#{config[:scheme]}://#{config[:server]}:#{config[:port]}#{resource}",
         
     | 
| 
      
 92 
     | 
    
         
            +
                                               ssl_ca_file: config[:cert_file].to_s,
         
     | 
| 
      
 93 
     | 
    
         
            +
                                               timeout: config[:timeout],
         
     | 
| 
      
 94 
     | 
    
         
            +
                                               headers: headers)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    else
         
     | 
| 
      
 96 
     | 
    
         
            +
                      RestClient::Resource.new("#{config[:scheme]}://#{config[:server]}:#{config[:port]}#{resource}",
         
     | 
| 
      
 97 
     | 
    
         
            +
                                               timeout: config[:timeout],
         
     | 
| 
      
 98 
     | 
    
         
            +
                                               headers: headers)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                JSON.parse(r.get)
         
     | 
| 
      
 101 
     | 
    
         
            +
              rescue Errno::ECONNREFUSED
         
     | 
| 
      
 102 
     | 
    
         
            +
                warning 'Connection refused'
         
     | 
| 
      
 103 
     | 
    
         
            +
              rescue RestClient::RequestTimeout
         
     | 
| 
      
 104 
     | 
    
         
            +
                critical 'Connection timed out'
         
     | 
| 
      
 105 
     | 
    
         
            +
              rescue RestClient::ServiceUnavailable
         
     | 
| 
      
 106 
     | 
    
         
            +
                critical 'Service is unavailable'
         
     | 
| 
      
 107 
     | 
    
         
            +
              rescue Errno::ECONNRESET
         
     | 
| 
      
 108 
     | 
    
         
            +
                critical 'Connection reset by peer'
         
     | 
| 
      
 109 
     | 
    
         
            +
              end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
              def master?
         
     | 
| 
      
 112 
     | 
    
         
            +
                state = get_es_resource('/_cluster/state/master_node')
         
     | 
| 
      
 113 
     | 
    
         
            +
                local = get_es_resource('/_nodes/_local')
         
     | 
| 
      
 114 
     | 
    
         
            +
                local['nodes'].keys.first == state['master_node']
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              def get_status(type)
         
     | 
| 
      
 118 
     | 
    
         
            +
                settings = get_es_resource('/_cluster/settings')
         
     | 
| 
      
 119 
     | 
    
         
            +
                # Get the status for the given type, or default to 'all'
         
     | 
| 
      
 120 
     | 
    
         
            +
                # which is the ES default
         
     | 
| 
      
 121 
     | 
    
         
            +
                begin
         
     | 
| 
      
 122 
     | 
    
         
            +
                  settings[type]['cluster']['routing']['allocation']['enable'].downcase
         
     | 
| 
      
 123 
     | 
    
         
            +
                rescue StandardError
         
     | 
| 
      
 124 
     | 
    
         
            +
                  'all'
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
              end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              def run
         
     | 
| 
      
 129 
     | 
    
         
            +
                if config[:allow_non_master] || master?
         
     | 
| 
      
 130 
     | 
    
         
            +
                  transient   = get_status('transient')
         
     | 
| 
      
 131 
     | 
    
         
            +
                  persistent  = get_status('persistent')
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  if transient == persistent
         
     | 
| 
      
 134 
     | 
    
         
            +
                    ok "Persistent and transient allocation match:  #{persistent}"
         
     | 
| 
      
 135 
     | 
    
         
            +
                  else
         
     | 
| 
      
 136 
     | 
    
         
            +
                    critical "Persistent(#{persistent}) and transient(#{transient}) \
         
     | 
| 
      
 137 
     | 
    
         
            +
                    shard allocation do not match."
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
                else
         
     | 
| 
      
 140 
     | 
    
         
            +
                  ok 'Not the master'
         
     | 
| 
      
 141 
     | 
    
         
            +
                end
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #! /usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            #   handler-es-delete-indices.rb
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            # DESCRIPTION:
         
     | 
| 
      
 6 
     | 
    
         
            +
            #   This handler deletes indices.
         
     | 
| 
      
 7 
     | 
    
         
            +
            #
         
     | 
| 
      
 8 
     | 
    
         
            +
            # OUTPUT:
         
     | 
| 
      
 9 
     | 
    
         
            +
            #   plain text
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # PLATFORMS:
         
     | 
| 
      
 12 
     | 
    
         
            +
            #   Linux
         
     | 
| 
      
 13 
     | 
    
         
            +
            #
         
     | 
| 
      
 14 
     | 
    
         
            +
            # DEPENDENCIES:
         
     | 
| 
      
 15 
     | 
    
         
            +
            #   gem: sensu-plugin
         
     | 
| 
      
 16 
     | 
    
         
            +
            #   gem: elasticsearch
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   gem: aws_es_transport
         
     | 
| 
      
 18 
     | 
    
         
            +
            #
         
     | 
| 
      
 19 
     | 
    
         
            +
            # USAGE:
         
     | 
| 
      
 20 
     | 
    
         
            +
            #   Deletes the indices given to it from a check output and a configured
         
     | 
| 
      
 21 
     | 
    
         
            +
            #     regex, and then deletes the indices matched.
         
     | 
| 
      
 22 
     | 
    
         
            +
            #
         
     | 
| 
      
 23 
     | 
    
         
            +
            # NOTES:
         
     | 
| 
      
 24 
     | 
    
         
            +
            #
         
     | 
| 
      
 25 
     | 
    
         
            +
            # LICENSE:
         
     | 
| 
      
 26 
     | 
    
         
            +
            #   Brendan Leon Gibat <brendan.gibat@gmail.com>
         
     | 
| 
      
 27 
     | 
    
         
            +
            #   Released under the same terms as Sensu (the MIT license); see LICENSE
         
     | 
| 
      
 28 
     | 
    
         
            +
            #   for details.
         
     | 
| 
      
 29 
     | 
    
         
            +
            #
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            require 'sensu-handler'
         
     | 
| 
      
 32 
     | 
    
         
            +
            require 'elasticsearch'
         
     | 
| 
      
 33 
     | 
    
         
            +
            require 'aws_es_transport'
         
     | 
| 
      
 34 
     | 
    
         
            +
            require 'sensu-plugins-elasticsearch'
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            class ESIndexCleanup < Sensu::Handler
         
     | 
| 
      
 37 
     | 
    
         
            +
              include ElasticsearchCommon
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              option :transport,
         
     | 
| 
      
 40 
     | 
    
         
            +
                     long: '--transport TRANSPORT',
         
     | 
| 
      
 41 
     | 
    
         
            +
                     description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              option :region,
         
     | 
| 
      
 44 
     | 
    
         
            +
                     long: '--region REGION',
         
     | 
| 
      
 45 
     | 
    
         
            +
                     description: 'Region (necessary for AWS Transport)'
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              option :host,
         
     | 
| 
      
 48 
     | 
    
         
            +
                     description: 'Elasticsearch host',
         
     | 
| 
      
 49 
     | 
    
         
            +
                     short: '-h HOST',
         
     | 
| 
      
 50 
     | 
    
         
            +
                     long: '--host HOST',
         
     | 
| 
      
 51 
     | 
    
         
            +
                     default: 'localhost'
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              option :port,
         
     | 
| 
      
 54 
     | 
    
         
            +
                     description: 'Elasticsearch port',
         
     | 
| 
      
 55 
     | 
    
         
            +
                     short: '-p PORT',
         
     | 
| 
      
 56 
     | 
    
         
            +
                     long: '--port PORT',
         
     | 
| 
      
 57 
     | 
    
         
            +
                     proc: proc(&:to_i),
         
     | 
| 
      
 58 
     | 
    
         
            +
                     default: 9200
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              option :scheme,
         
     | 
| 
      
 61 
     | 
    
         
            +
                     description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
         
     | 
| 
      
 62 
     | 
    
         
            +
                     short: '-s SCHEME',
         
     | 
| 
      
 63 
     | 
    
         
            +
                     long: '--scheme SCHEME'
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              option :password,
         
     | 
| 
      
 66 
     | 
    
         
            +
                     description: 'Elasticsearch connection password',
         
     | 
| 
      
 67 
     | 
    
         
            +
                     short: '-P PASSWORD',
         
     | 
| 
      
 68 
     | 
    
         
            +
                     long: '--password PASSWORD'
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              option :user,
         
     | 
| 
      
 71 
     | 
    
         
            +
                     description: 'Elasticsearch connection user',
         
     | 
| 
      
 72 
     | 
    
         
            +
                     short: '-u USER',
         
     | 
| 
      
 73 
     | 
    
         
            +
                     long: '--user USER'
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              option :timeout,
         
     | 
| 
      
 76 
     | 
    
         
            +
                     description: 'Elasticsearch query timeout in seconds',
         
     | 
| 
      
 77 
     | 
    
         
            +
                     short: '-t TIMEOUT',
         
     | 
| 
      
 78 
     | 
    
         
            +
                     long: '--timeout TIMEOUT',
         
     | 
| 
      
 79 
     | 
    
         
            +
                     proc: proc(&:to_i),
         
     | 
| 
      
 80 
     | 
    
         
            +
                     default: 60
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              option :event_regex,
         
     | 
| 
      
 83 
     | 
    
         
            +
                     description: 'Elasticsearch connection user',
         
     | 
| 
      
 84 
     | 
    
         
            +
                     short: '-e EVENT_REGEX',
         
     | 
| 
      
 85 
     | 
    
         
            +
                     long: '--event-regex EVENT_REGEX',
         
     | 
| 
      
 86 
     | 
    
         
            +
                     default: 'INDEX\[([^\]]+)\]'
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              def handle
         
     | 
| 
      
 89 
     | 
    
         
            +
                event_regex = Regexp.new(config[:event_regex])
         
     | 
| 
      
 90 
     | 
    
         
            +
                indices_to_delete = @event['check']['output'].scan(event_regex).flatten
         
     | 
| 
      
 91 
     | 
    
         
            +
                if !indices_to_delete.nil? && !indices_to_delete.empty?
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  puts("Deleting indices: [ #{indices_to_delete.sort.join(', ')} ]")
         
     | 
| 
      
 94 
     | 
    
         
            +
                  client.indices.delete index: indices_to_delete
         
     | 
| 
      
 95 
     | 
    
         
            +
                else
         
     | 
| 
      
 96 
     | 
    
         
            +
                  puts('No indices matched pattern to delete.')
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,215 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #! /usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            #   es-cluster-metrics
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            # DESCRIPTION:
         
     | 
| 
      
 6 
     | 
    
         
            +
            #   This plugin uses the ES API to collect metrics, producing a JSON
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   document which is outputted to STDOUT. An exit status of 0 indicates
         
     | 
| 
      
 8 
     | 
    
         
            +
            #   the plugin has successfully collected and produced metrics.
         
     | 
| 
      
 9 
     | 
    
         
            +
            #
         
     | 
| 
      
 10 
     | 
    
         
            +
            # OUTPUT:
         
     | 
| 
      
 11 
     | 
    
         
            +
            #   metric data
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # PLATFORMS:
         
     | 
| 
      
 14 
     | 
    
         
            +
            #   Linux
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
      
 16 
     | 
    
         
            +
            # DEPENDENCIES:
         
     | 
| 
      
 17 
     | 
    
         
            +
            #   gem: sensu-plugin
         
     | 
| 
      
 18 
     | 
    
         
            +
            #   gem: rest-client
         
     | 
| 
      
 19 
     | 
    
         
            +
            #
         
     | 
| 
      
 20 
     | 
    
         
            +
            # USAGE:
         
     | 
| 
      
 21 
     | 
    
         
            +
            #   #YELLOW
         
     | 
| 
      
 22 
     | 
    
         
            +
            #
         
     | 
| 
      
 23 
     | 
    
         
            +
            # NOTES:
         
     | 
| 
      
 24 
     | 
    
         
            +
            #
         
     | 
| 
      
 25 
     | 
    
         
            +
            # LICENSE:
         
     | 
| 
      
 26 
     | 
    
         
            +
            #   Copyright 2011 Sonian, Inc <chefs@sonian.net>
         
     | 
| 
      
 27 
     | 
    
         
            +
            #   Released under the same terms as Sensu (the MIT license); see LICENSE
         
     | 
| 
      
 28 
     | 
    
         
            +
            #   for details.
         
     | 
| 
      
 29 
     | 
    
         
            +
            #
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            require 'sensu-plugin/metric/cli'
         
     | 
| 
      
 32 
     | 
    
         
            +
            require 'rest-client'
         
     | 
| 
      
 33 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 34 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            #
         
     | 
| 
      
 37 
     | 
    
         
            +
            # ES Cluster Metrics
         
     | 
| 
      
 38 
     | 
    
         
            +
            #
         
     | 
| 
      
 39 
     | 
    
         
            +
            class ESClusterMetrics < Sensu::Plugin::Metric::CLI::Graphite
         
     | 
| 
      
 40 
     | 
    
         
            +
              option :scheme,
         
     | 
| 
      
 41 
     | 
    
         
            +
                     description: 'Metric naming scheme, text to prepend to metric',
         
     | 
| 
      
 42 
     | 
    
         
            +
                     short: '-s SCHEME',
         
     | 
| 
      
 43 
     | 
    
         
            +
                     long: '--scheme SCHEME',
         
     | 
| 
      
 44 
     | 
    
         
            +
                     default: "#{Socket.gethostname}.elasticsearch.cluster"
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              option :host,
         
     | 
| 
      
 47 
     | 
    
         
            +
                     description: 'Elasticsearch host',
         
     | 
| 
      
 48 
     | 
    
         
            +
                     short: '-h HOST',
         
     | 
| 
      
 49 
     | 
    
         
            +
                     long: '--host HOST',
         
     | 
| 
      
 50 
     | 
    
         
            +
                     default: 'localhost'
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              option :port,
         
     | 
| 
      
 53 
     | 
    
         
            +
                     description: 'Elasticsearch port',
         
     | 
| 
      
 54 
     | 
    
         
            +
                     short: '-p PORT',
         
     | 
| 
      
 55 
     | 
    
         
            +
                     long: '--port PORT',
         
     | 
| 
      
 56 
     | 
    
         
            +
                     proc: proc(&:to_i),
         
     | 
| 
      
 57 
     | 
    
         
            +
                     default: 9200
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              option :timeout,
         
     | 
| 
      
 60 
     | 
    
         
            +
                     description: 'Sets the connection timeout for REST client',
         
     | 
| 
      
 61 
     | 
    
         
            +
                     short: '-t SECS',
         
     | 
| 
      
 62 
     | 
    
         
            +
                     long: '--timeout SECS',
         
     | 
| 
      
 63 
     | 
    
         
            +
                     proc: proc(&:to_i),
         
     | 
| 
      
 64 
     | 
    
         
            +
                     default: 30
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              option :allow_non_master,
         
     | 
| 
      
 67 
     | 
    
         
            +
                     description: 'Allow check to run on non-master nodes',
         
     | 
| 
      
 68 
     | 
    
         
            +
                     short: '-a',
         
     | 
| 
      
 69 
     | 
    
         
            +
                     long: '--allow-non-master',
         
     | 
| 
      
 70 
     | 
    
         
            +
                     default: false
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              option :enable_percolate,
         
     | 
| 
      
 73 
     | 
    
         
            +
                     description: 'Enables percolator stats (ES 2 and older only)',
         
     | 
| 
      
 74 
     | 
    
         
            +
                     short: '-o',
         
     | 
| 
      
 75 
     | 
    
         
            +
                     long: '--enable-percolate',
         
     | 
| 
      
 76 
     | 
    
         
            +
                     default: false
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              option :user,
         
     | 
| 
      
 79 
     | 
    
         
            +
                     description: 'Elasticsearch User',
         
     | 
| 
      
 80 
     | 
    
         
            +
                     short: '-u USER',
         
     | 
| 
      
 81 
     | 
    
         
            +
                     long: '--user USER'
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              option :password,
         
     | 
| 
      
 84 
     | 
    
         
            +
                     description: 'Elasticsearch Password',
         
     | 
| 
      
 85 
     | 
    
         
            +
                     short: '-P PASS',
         
     | 
| 
      
 86 
     | 
    
         
            +
                     long: '--password PASS'
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              option :https,
         
     | 
| 
      
 89 
     | 
    
         
            +
                     description: 'Enables HTTPS',
         
     | 
| 
      
 90 
     | 
    
         
            +
                     short: '-e',
         
     | 
| 
      
 91 
     | 
    
         
            +
                     long: '--https'
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              option :cert_file,
         
     | 
| 
      
 94 
     | 
    
         
            +
                     description: 'Cert file to use',
         
     | 
| 
      
 95 
     | 
    
         
            +
                     long: '--cert-file CERT_FILE'
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              def acquire_es_version
         
     | 
| 
      
 98 
     | 
    
         
            +
                info = get_es_resource('/')
         
     | 
| 
      
 99 
     | 
    
         
            +
                info['version']['number']
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              def get_es_resource(resource)
         
     | 
| 
      
 103 
     | 
    
         
            +
                headers = {}
         
     | 
| 
      
 104 
     | 
    
         
            +
                if config[:user] && config[:password]
         
     | 
| 
      
 105 
     | 
    
         
            +
                  auth = 'Basic ' + Base64.strict_encode64("#{config[:user]}:#{config[:password]}").chomp
         
     | 
| 
      
 106 
     | 
    
         
            +
                  headers = { 'Authorization' => auth }
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                protocol = if config[:https]
         
     | 
| 
      
 110 
     | 
    
         
            +
                             'https'
         
     | 
| 
      
 111 
     | 
    
         
            +
                           else
         
     | 
| 
      
 112 
     | 
    
         
            +
                             'http'
         
     | 
| 
      
 113 
     | 
    
         
            +
                           end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                r = if config[:cert_file]
         
     | 
| 
      
 116 
     | 
    
         
            +
                      RestClient::Resource.new("#{protocol}://#{config[:host]}:#{config[:port]}#{resource}",
         
     | 
| 
      
 117 
     | 
    
         
            +
                                               ssl_ca_file: config[:cert_file].to_s,
         
     | 
| 
      
 118 
     | 
    
         
            +
                                               timeout: config[:timeout],
         
     | 
| 
      
 119 
     | 
    
         
            +
                                               headers: headers)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    else
         
     | 
| 
      
 121 
     | 
    
         
            +
                      RestClient::Resource.new("#{protocol}://#{config[:host]}:#{config[:port]}#{resource}",
         
     | 
| 
      
 122 
     | 
    
         
            +
                                               timeout: config[:timeout],
         
     | 
| 
      
 123 
     | 
    
         
            +
                                               headers: headers)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
                ::JSON.parse(r.get)
         
     | 
| 
      
 126 
     | 
    
         
            +
              rescue Errno::ECONNREFUSED
         
     | 
| 
      
 127 
     | 
    
         
            +
                warning 'Connection refused'
         
     | 
| 
      
 128 
     | 
    
         
            +
              rescue RestClient::RequestTimeout
         
     | 
| 
      
 129 
     | 
    
         
            +
                warning 'Connection timed out'
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
              def master?
         
     | 
| 
      
 133 
     | 
    
         
            +
                state = if Gem::Version.new(acquire_es_version) >= Gem::Version.new('3.0.0')
         
     | 
| 
      
 134 
     | 
    
         
            +
                          get_es_resource('/_cluster/state/master_node')
         
     | 
| 
      
 135 
     | 
    
         
            +
                        else
         
     | 
| 
      
 136 
     | 
    
         
            +
                          get_es_resource('/_cluster/state?filter_routing_table=true&filter_metadata=true&filter_indices=true')
         
     | 
| 
      
 137 
     | 
    
         
            +
                        end
         
     | 
| 
      
 138 
     | 
    
         
            +
                local = if Gem::Version.new(acquire_es_version) >= Gem::Version.new('1.0.0')
         
     | 
| 
      
 139 
     | 
    
         
            +
                          get_es_resource('/_nodes/_local')
         
     | 
| 
      
 140 
     | 
    
         
            +
                        else
         
     | 
| 
      
 141 
     | 
    
         
            +
                          get_es_resource('/_cluster/nodes/_local')
         
     | 
| 
      
 142 
     | 
    
         
            +
                        end
         
     | 
| 
      
 143 
     | 
    
         
            +
                local['nodes'].keys.first == state['master_node']
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
              def acquire_health
         
     | 
| 
      
 147 
     | 
    
         
            +
                health = get_es_resource('/_cluster/health').reject { |k, _v| %w[cluster_name timed_out].include?(k) }
         
     | 
| 
      
 148 
     | 
    
         
            +
                health['status'] = %w[red yellow green].index(health['status'])
         
     | 
| 
      
 149 
     | 
    
         
            +
                health
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
              def acquire_document_count
         
     | 
| 
      
 153 
     | 
    
         
            +
                document_count = get_es_resource('/_stats/docs')
         
     | 
| 
      
 154 
     | 
    
         
            +
                count = document_count['_all']['total']
         
     | 
| 
      
 155 
     | 
    
         
            +
                if count.empty?
         
     | 
| 
      
 156 
     | 
    
         
            +
                  return 0
         
     | 
| 
      
 157 
     | 
    
         
            +
                else
         
     | 
| 
      
 158 
     | 
    
         
            +
                  return count['docs']['count']
         
     | 
| 
      
 159 
     | 
    
         
            +
                end
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
              def acquire_cluster_metrics
         
     | 
| 
      
 163 
     | 
    
         
            +
                cluster_stats = get_es_resource('/_cluster/stats')
         
     | 
| 
      
 164 
     | 
    
         
            +
                cluster_metrics = Hash.new { |h, k| h[k] = {} }
         
     | 
| 
      
 165 
     | 
    
         
            +
                cluster_metrics['fs']['total_in_bytes'] = cluster_stats['nodes']['fs']['total_in_bytes']
         
     | 
| 
      
 166 
     | 
    
         
            +
                cluster_metrics['fs']['free_in_bytes'] = cluster_stats['nodes']['fs']['free_in_bytes']
         
     | 
| 
      
 167 
     | 
    
         
            +
                cluster_metrics['fs']['store_in_bytes'] = cluster_stats['indices']['store']['size_in_bytes']
         
     | 
| 
      
 168 
     | 
    
         
            +
                cluster_metrics['fs']['disk_reads'] = cluster_stats['nodes']['fs']['disk_reads']
         
     | 
| 
      
 169 
     | 
    
         
            +
                cluster_metrics['fs']['disk_writes'] = cluster_stats['nodes']['fs']['disk_writes']
         
     | 
| 
      
 170 
     | 
    
         
            +
                cluster_metrics['fs']['disk_read_size_in_bytes'] = cluster_stats['nodes']['fs']['disk_read_size_in_bytes']
         
     | 
| 
      
 171 
     | 
    
         
            +
                cluster_metrics['fs']['disk_write_size_in_bytes'] = cluster_stats['nodes']['fs']['disk_write_size_in_bytes']
         
     | 
| 
      
 172 
     | 
    
         
            +
                cluster_metrics['fielddata']['memory_size_in_bytes'] = cluster_stats['indices']['fielddata']['memory_size_in_bytes']
         
     | 
| 
      
 173 
     | 
    
         
            +
                cluster_metrics['fielddata']['evictions'] = cluster_stats['indices']['fielddata']['evictions']
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                # Elasticsearch changed the name filter_cache to query_cache in 2.0+
         
     | 
| 
      
 176 
     | 
    
         
            +
                cache_name = Gem::Version.new(acquire_es_version) < Gem::Version.new('2.0.0') ? 'filter_cache' : 'query_cache'
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                cluster_metrics[cache_name]['memory_size_in_bytes'] = cluster_stats['indices'][cache_name]['memory_size_in_bytes']
         
     | 
| 
      
 179 
     | 
    
         
            +
                cluster_metrics[cache_name]['evictions'] = cluster_stats['indices'][cache_name]['evictions']
         
     | 
| 
      
 180 
     | 
    
         
            +
                cluster_metrics['mem'] = cluster_stats['nodes']['jvm']['mem']
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                if config[:enable_percolate] && Gem::Version.new(acquire_es_version) < Gem::Version.new('5.0.0')
         
     | 
| 
      
 183 
     | 
    
         
            +
                  cluster_metrics['percolate']['total'] = cluster_stats['indices']['percolate']['total']
         
     | 
| 
      
 184 
     | 
    
         
            +
                  cluster_metrics['percolate']['time_in_millis'] = cluster_stats['indices']['percolate']['time_in_millis']
         
     | 
| 
      
 185 
     | 
    
         
            +
                  cluster_metrics['percolate']['queries'] = cluster_stats['indices']['percolate']['queries']
         
     | 
| 
      
 186 
     | 
    
         
            +
                end
         
     | 
| 
      
 187 
     | 
    
         
            +
                cluster_metrics
         
     | 
| 
      
 188 
     | 
    
         
            +
              end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
              def acquire_allocation_status
         
     | 
| 
      
 191 
     | 
    
         
            +
                cluster_config = get_es_resource('/_cluster/settings')
         
     | 
| 
      
 192 
     | 
    
         
            +
                transient_settings = cluster_config['transient']
         
     | 
| 
      
 193 
     | 
    
         
            +
                if transient_settings.key?('cluster')
         
     | 
| 
      
 194 
     | 
    
         
            +
                  return %w[none new_primaries primaries all].index(transient_settings['cluster']['routing']['allocation']['enable'])
         
     | 
| 
      
 195 
     | 
    
         
            +
                else
         
     | 
| 
      
 196 
     | 
    
         
            +
                  return nil
         
     | 
| 
      
 197 
     | 
    
         
            +
                end
         
     | 
| 
      
 198 
     | 
    
         
            +
              end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
              def run
         
     | 
| 
      
 201 
     | 
    
         
            +
                if config[:allow_non_master] || master?
         
     | 
| 
      
 202 
     | 
    
         
            +
                  acquire_health.each do |k, v|
         
     | 
| 
      
 203 
     | 
    
         
            +
                    output(config[:scheme] + '.' + k, v)
         
     | 
| 
      
 204 
     | 
    
         
            +
                  end
         
     | 
| 
      
 205 
     | 
    
         
            +
                  acquire_cluster_metrics.each do |cluster_metric|
         
     | 
| 
      
 206 
     | 
    
         
            +
                    cluster_metric[1].each do |k, v|
         
     | 
| 
      
 207 
     | 
    
         
            +
                      output(config[:scheme] + '.' + cluster_metric[0] + '.' + k, v || 0)
         
     | 
| 
      
 208 
     | 
    
         
            +
                    end
         
     | 
| 
      
 209 
     | 
    
         
            +
                  end
         
     | 
| 
      
 210 
     | 
    
         
            +
                  output(config[:scheme] + '.document_count', acquire_document_count)
         
     | 
| 
      
 211 
     | 
    
         
            +
                  output(config[:scheme] + '.allocation_status', acquire_allocation_status) unless acquire_allocation_status.nil?
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
                ok
         
     | 
| 
      
 214 
     | 
    
         
            +
              end
         
     | 
| 
      
 215 
     | 
    
         
            +
            end
         
     |