sensu-plugins/sensu-plugins-apache

View on GitHub
bin/metrics-apache-graphite.rb

Summary

Maintainability
A
1 hr
Test Coverage
#! /usr/bin/env ruby
# frozen_string_literal: true

#
# apache-graphite
#
# DESCRIPTION:
#   This plugin retrieves machine-readable output of mod_status, parses
#   it, and generates Apache process metrics formatted for Graphite.
#
# OUTPUT:
#   metric data
#
# PLATFORMS:
#   Linux
#
# DEPENDENCIES:
#   gem: sensu-plugin
#   Apache module: mod_status
#
# USAGE:
#  #YELLOW
#
# NOTES:
#   enable extended mod_status
#
# LICENSE:
#   Copyright 2014 Sonian, Inc. and contributors. <support@sensuapp.org>
#   Released under the same terms as Sensu (the MIT license); see LICENSE
#   for details.
#

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

#
# Apache Metrics
#
class ApacheMetrics < Sensu::Plugin::Metric::CLI::Graphite
  option :host,
         short: '-h HOST',
         long: '--host HOST',
         description: 'HOST to check mod_status output',
         default: 'localhost'

  option :port,
         short: '-p PORT',
         long: '--port PORT',
         description: 'Port to check mod_status output',
         default: '80'

  option :path,
         short: '-path PATH',
         long: '--path PATH',
         description: 'PATH to check mod_status output',
         default: '/server-status?auto'

  option :user,
         short: '-user USER',
         long: '--user USER',
         description: 'User if HTTP Basic is used'

  option :password,
         short: '-password USER',
         long: '--password USER',
         description: 'Password if HTTP Basic is used'

  option :scheme,
         description: 'Metric naming scheme, text to prepend to .$parent.$child',
         long: '--scheme SCHEME',
         default: Socket.gethostname.to_s

  option :secure,
         short: '-s',
         long: '--secure',
         description: 'Use SSL'

  def acquire_mod_status
    http = Net::HTTP.new(config[:host], config[:port])
    if config[:secure]
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
      http.use_ssl = true
    end
    req = Net::HTTP::Get.new(config[:path])
    if !config[:user].nil? && !config[:password].nil?
      req.basic_auth config[:user], config[:password]
    end
    res = http.request(req)
    case res.code
    when '200'
      res.body
    else
      critical "Unable to get Apache metrics, unexpected HTTP response code: #{res.code}"
    end
  end

  def run
    timestamp = Time.now.to_i
    stats = {}
    acquire_mod_status.split("\n").each do |line| # rubocop:disable Metrics/BlockLength
      name, value = line.split(': ')
      case name
      when 'Total Accesses'
        stats['total_accesses'] = value.to_i
      when 'Total kBytes'
        stats['total_bytes'] = (value.to_f * 1024).to_i
      when 'CPULoad'
        stats['cpuload'] = value.to_f * 100
      when 'BusyWorkers'
        stats['busy_workers'] = value.to_i
      when 'IdleWorkers'
        stats['idle_workers'] = value.to_i
      when 'ReqPerSec'
        stats['requests_per_sec'] = value.to_f
      when 'BytesPerSec'
        stats['bytes_per_sec'] = value.to_f
      when 'BytesPerReq'
        stats['bytes_per_req'] = value.to_f
      when 'Scoreboard'
        value = value.strip
        stats['open'] = value.count('.')
        stats['waiting'] = value.count('_')
        stats['starting'] = value.count('S')
        stats['reading'] = value.count('R')
        stats['sending'] = value.count('W')
        stats['keepalive'] = value.count('K')
        stats['dnslookup'] = value.count('D')
        stats['closing'] = value.count('C')
        stats['logging'] = value.count('L')
        stats['finishing'] = value.count('G')
        stats['idle_cleanup'] = value.count('I')
        stats['total'] = value.length
      end
    end
    metrics = {
      apache: stats
    }
    metrics.each do |parent, children|
      children.each do |child, value|
        output [config[:scheme], parent, child].join('.'), value, timestamp
      end
    end
    ok
  end
end