bin/riemann-consul in riemann-tools-1.0.0 vs bin/riemann-consul in riemann-tools-1.1.0

- old
+ new

@@ -1,107 +1,113 @@ #!/usr/bin/env ruby -Process.setproctitle($0) +# frozen_string_literal: true +Process.setproctitle($PROGRAM_NAME) + # Reports service and node status to riemann -require File.expand_path('../../lib/riemann/tools', __FILE__) +require File.expand_path('../lib/riemann/tools', __dir__) require 'socket' require 'net/http' require 'uri' require 'json' -class Riemann::Tools::ConsulHealth - include Riemann::Tools +module Riemann + module Tools + class ConsulHealth + include Riemann::Tools - opt :consul_host, "Consul API Host (default to localhost)", :default => "localhost" - opt :consul_port, "Consul API Host (default to 8500)", :default => "8500" - opt :prefix, "prefix to use for all service names when reporting", :default => "consul " - opt :minimum_services_per_node, "minimum services per node (default: 0)", :default => 0 + opt :consul_host, 'Consul API Host (default to localhost)', default: 'localhost' + opt :consul_port, 'Consul API Host (default to 8500)', default: '8500' + opt :prefix, 'prefix to use for all service names when reporting', default: 'consul ' + opt :minimum_services_per_node, 'minimum services per node (default: 0)', default: 0 - def initialize + def initialize + @hostname = opts[:consul_host] + @prefix = opts[:prefix] + @minimum_services_per_node = opts[:minimum_services_per_node] + @underlying_ip = IPSocket.getaddress(@hostname) + @consul_leader_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/status/leader") + @consul_services_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/catalog/services") + @consul_nodes_url = URI.parse("http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/catalog/nodes") + @consul_health_url_prefix = "http://#{opts[:consul_host]}:#{opts[:consul_port]}/v1/health/service/" - @hostname = opts[:consul_host] - @prefix = opts[:prefix] - @minimum_services_per_node = opts[:minimum_services_per_node] - @underlying_ip = IPSocket.getaddress(@hostname) - @consul_leader_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/status/leader") - @consul_services_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/catalog/services") - @consul_nodes_url = URI.parse("http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/catalog/nodes") - @consul_health_url_prefix = "http://" + opts[:consul_host] + ":" + opts[:consul_port] + "/v1/health/service/" + @last_services_read = {} + end - @last_services_read = Hash.new + def alert(hostname, service, state, metric, description) + opts = { + host: hostname, + service: service.to_s, + state: state.to_s, + metric: metric, + description: description, + } - end + report(opts) + end - def alert(hostname, service, state, metric, description) + def get(url) + Net::HTTP.get_response(url).body + end - opts = { :host => hostname, - :service => service.to_s, - :state => state.to_s, - :metric => metric, - :description => description } + def tick + leader = JSON.parse(get(@consul_leader_url)) + leader_hostname = URI.parse("http://#{leader}").hostname - report(opts) - end + return unless leader_hostname == @underlying_ip - def get(url) - Net::HTTP.get_response(url).body - end + nodes = JSON.parse(get(@consul_nodes_url)) + services = JSON.parse(get(@consul_services_url)) + services_by_nodes = {} - def tick + nodes.each do |node| + node_name = node['Node'] + services_by_nodes[node_name] = 0 + end - leader = JSON.parse(get(@consul_leader_url)) - leader_hostname = URI.parse("http://" + leader).hostname + # For every service + services.each do |service| + service_name = service[0] + health_url = URI.parse(@consul_health_url_prefix + service_name) + health_nodes = JSON.parse(get(health_url)) - if (leader_hostname == @underlying_ip) - nodes = JSON.parse(get(@consul_nodes_url)) - services = JSON.parse(get(@consul_services_url)) - services_by_nodes = Hash.new + total_count = 0 + ok_count = 0 - for node in nodes - node_name = node["Node"] - services_by_nodes[node_name] = 0 - end + health_nodes.each do |node| + hostname = node['Node']['Node'] + ok = node['Checks'].all? { |check| check['Status'] == 'passing' } + alert(hostname, "#{@prefix}#{service_name}", ok ? :ok : :critical, ok ? 1 : 0, JSON.generate(node)) + total_count += 1 + ok_count += ok ? 1 : 0 + last_services_by_nodes = services_by_nodes[hostname].to_i + services_by_nodes[hostname] = last_services_by_nodes + 1 + end - # For every service - for service in services - service_name = service[0] - health_url = URI.parse(@consul_health_url_prefix + service_name) - health_nodes = JSON.parse(get(health_url)) + unless @last_services_read[service_name].nil? + last_ok = @last_services_read[service_name] + if last_ok != ok_count + alert( + 'total', "#{@prefix}#{service_name}-count", ok_count >= last_ok ? :ok : :critical, ok_count, + "Number of passing #{service_name} is: #{ok_count}/#{total_count}, Last time it was: #{last_ok}", + ) + end + end - totalCount = 0 - okCount = 0 - - for node in health_nodes - hostname = node["Node"]["Node"] - ok = node["Checks"].all? {|check| check["Status"] == "passing"} - alert(hostname, "#{@prefix}#{service_name}", ok ? :ok : :critical, ok ? 1 : 0, JSON.generate(node)) - totalCount += 1 - okCount += ok ? 1 : 0 - - last_services_by_nodes = services_by_nodes[hostname].to_i - services_by_nodes[hostname] = last_services_by_nodes + 1 + @last_services_read[service_name] = ok_count end - if (@last_services_read[service_name] != nil) - lastOk = @last_services_read[service_name] - if (lastOk != okCount) - alert("total", "#{@prefix}#{service_name}-count", okCount >= lastOk ? :ok : :critical, okCount, "Number of passing #{service_name} is: #{okCount}/#{totalCount}, Last time it was: #{lastOk}") - end + # For every node + services_by_nodes.each do |node, count| + alert( + node, "#{@prefix}total-services", count >= @minimum_services_per_node ? :ok : :critical, count, + "#{count} services in the specified node", + ) end - - @last_services_read[service_name] = okCount - end - - # For every node - for node,count in services_by_nodes - alert(node, "#{@prefix}total-services", (count >= @minimum_services_per_node) ? :ok : :critical, count, "#{count} services in the specified node") - end - end - end end Riemann::Tools::ConsulHealth.run