sensu-plugins/sensu-plugins-nginx

View on GitHub
bin/metrics-nginx.rb

Summary

Maintainability
B
6 hrs
Test Coverage
#! /usr/bin/env ruby
# frozen_string_literal: true

#
#   nginx-metrics
#
# DESCRIPTION:
#   Pull nginx metrics for backends through stub status module
#
# OUTPUT:
#   metric data
#
# PLATFORMS:
#   Linux
#
# DEPENDENCIES:
#   gem: sensu-plugin
#
# USAGE:
#   metrics-nginx.rb -h hostname -p port -q status_path
#   metrics-nginx.rb -u http://hostname:port/status_path
#
# NOTES:
#
# LICENSE:
#   Copyright 2012 Pete Shima <me@peteshima.com>
#   Released under the same terms as Sensu (the MIT license); see LICENSE
#   for details.
#

require 'sensu-plugin/metric/cli'
require 'net/https'
require 'uri'
require 'socket'

#
# Nginx Metrics
#
class NginxMetrics < Sensu::Plugin::Metric::CLI::Graphite
  option :url,
         short: '-u URL',
         long: '--url URL',
         description: 'Full URL to nginx status page, example: https://yoursite.com/nginx_status This ignores ALL other options EXCEPT --scheme'

  option :hostname,
         short: '-h HOSTNAME',
         long: '--host HOSTNAME',
         description: 'Nginx hostname',
         default: 'localhost'

  option :port,
         short: '-p PORT',
         long: '--port PORT',
         description: 'Nginx  port',
         default: '80'

  option :path,
         short: '-q STATUSPATH',
         long: '--statspath STATUSPATH',
         description: 'Path to your stub status module',
         default: 'nginx_status'

  option :hostheader,
         long: '--hostheader HOSTHEADER',
         description: 'Set the Host header to this string'
  option :token,
         long: '--token token',
         description: 'JWT Token'

  option :scheme,
         description: 'Metric naming scheme, text to prepend to metric',
         short: '-s SCHEME',
         long: '--scheme SCHEME',
         default: "#{Socket.gethostname}.nginx"

  # Main function
  #
  def run
    found = false
    attempts = 0
    until found || attempts >= 10
      attempts += 1
      if config[:url]
        uri = URI.parse(config[:url])
        http = Net::HTTP.new(uri.host, uri.port)
        if uri.scheme == 'https'
          http.use_ssl = true
          http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        end
        request = Net::HTTP::Get.new(uri.request_uri)
        if config[:hostheader]
          request['Host'] = config[:hostheader]
        end
        if config[:token]
          request['Authorization'] = "Bearer #{config[:token]}"
        end
        response = http.request(request)
        if response.code == '200'
          found = true
        elsif !response.header['location'].nil?
          config[:url] = response.header['location']
        end
      else
        response = Net::HTTP.start(config[:hostname], config[:port]) do |connection|
          request = Net::HTTP::Get.new("/#{config[:path]}")
          connection.request(request)
        end
      end
    end

    # #YELLOW
    response.body.split(/\r?\n/).each do |line|
      if line =~ /^Active connections:\s+(\d+)/
        connections = line.match(/^Active connections:\s+(\d+)/).to_a
        output "#{config[:scheme]}.active_connections", connections[1]
      end
      if line =~ /^\s+(\d+)\s+(\d+)\s+(\d+)/
        requests = line.match(/^\s+(\d+)\s+(\d+)\s+(\d+)/).to_a
        output "#{config[:scheme]}.accepts", requests[1]
        output "#{config[:scheme]}.handled", requests[2]
        output "#{config[:scheme]}.requests", requests[3]
      end
      if line =~ /^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/
        queue = line.match(/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/).to_a
        output "#{config[:scheme]}.reading", queue[1]
        output "#{config[:scheme]}.writing", queue[2]
        output "#{config[:scheme]}.waiting", queue[3]
      end
    end
    ok
  end
end