sensu-plugins/sensu-plugins-sensu

View on GitHub
bin/metrics-aggregate.rb

Summary

Maintainability
A
0 mins
Test Coverage
#!/usr/bin/env ruby
# frozen_string_literal: false

#
# Aggregate Metrics
#
# Walks the /aggregates API to return metrics for
# the aggregated output states of each check.
#
# sensu.aggregates.some_aggregated_check.clients 1 1380251999
# sensu.aggregates.some_aggregated_check.checks 125 1380251999
# sensu.aggregates.some_aggregated_check.ok 125 1380251999
# sensu.aggregates.some_aggregated_check.warning  0 1380251999
# sensu.aggregates.some_aggregated_check.critical 0 1380251999
# sensu.aggregates.some_aggregated_check.unknown  0 1380251999
# sensu.aggregates.some_aggregated_check.total  125 1380251999
# sensu.aggregates.some_aggregated_check.stale  0 1380251999
# ===
#
# Authors
# ===
# Sean Porter, @portertech
# Nick Stielau, @nstielau
#
# Copyright 2013 Nick Stielau
# Copyright 2012 Sonian, Inc.
#
# Released under the same terms as Sensu (the MIT license); see
# LICENSE for details.

require 'sensu-plugin/metric/cli'
require 'json'
require 'net/http'
require 'net/https'

class AggregateMetrics < Sensu::Plugin::Metric::CLI::Generic
  option :api,
         short: '-a URL',
         long: '--api URL',
         description: 'Sensu API URL',
         default: 'http://localhost:4567'

  option :user,
         short: '-u USER',
         long: '--user USER',
         description: 'Sensu API USER'

  option :password,
         short: '-p PASSOWRD',
         long: '--password PASSWORD',
         description: 'Sensu API PASSWORD'

  option :timeout,
         short: '-t SECONDS',
         long: '--timeout SECONDS',
         description: 'Sensu API connection timeout in SECONDS',
         proc: proc(&:to_i),
         default: 30

  option :age,
         short: '-A SECONDS',
         long: '--age SECONDS',
         description: 'Minimum aggregate age in SECONDS, time since check request issued',
         default: 30,
         proc: proc(&:to_i)

  option :scheme,
         description: 'Metric naming scheme for graphite format',
         long: '--scheme SCHEME',
         default: "#{Socket.gethostname}.sensu.aggregates"

  option :measurement,
         description: 'Measurement for influxdb format',
         long: '--measurement MEASUREMENT',
         default: 'sensu.aggregates'

  option :debug,
         long: '--debug',
         description: 'Verbose output'

  def api_request(resource)
    uri = URI.parse(config[:api])
    http = Net::HTTP.new(uri.host, uri.port)
    if uri.scheme == 'https'
      http.use_ssl = true
    end
    req = Net::HTTP::Get.new(resource)
    r = http.request(req)
    ::JSON.parse(r.body)
  rescue Errno::ECONNREFUSED
    warning 'Connection refused'
  rescue Timeout::Error
    warning 'Connection timed out'
  rescue ::JSON::ParserError
    warning 'Sensu API returned invalid JSON'
  end

  def acquire_checks
    uri = '/aggregates'
    checks = api_request(uri)
    puts "Checks: #{checks.inspect}" if config[:debug]
    checks
  end

  def get_aggregate(check)
    uri = "/aggregates/#{check}"
    issued = api_request(uri + "?max_age=#{config[:age]}")
    if issued.empty?
      warning "No aggregates for #{check}"
    else
      issued
    end
  end

  def run
    timestamp = Time.now.to_i
    acquire_checks.each do |check|
      aggregate = get_aggregate(check['name'])
      puts "#{check['name']} aggregates: #{aggregate}" if config[:debug]
      aggregate.each_value do |count|
        count.each do |x, y|
          output metric_name: x,
                 value: y,
                 graphite_metric_path: "#{config[:scheme]}.#{check['name']}.#{x}",
                 statsd_metric_name: "#{config[:scheme]}.#{check['name']}.#{x}",
                 influxdb_measurement: config[:measurement],
                 tags: {
                   check: check['name'],
                   host: Socket.gethostname
                 },
                 timestamp: timestamp
        end
      end
    end
    ok
  end
end