sensu-plugins/sensu-plugins-aws

View on GitHub
bin/metrics-rds.rb

Summary

Maintainability
A
2 hrs
Test Coverage
#! /usr/bin/env ruby
#
# rds-metrics
#
# DESCRIPTION:
#   Gets RDS metrics from CloudWatch and puts them in Graphite for longer term storage
#
# OUTPUT:
#   metric-data
#
# PLATFORMS:
#   Linux
#
# DEPENDENCIES:
#   gem: sensu-plugin
#
# USAGE:
#   rds-metrics --aws-region eu-west-1
#   rds-metrics --aws-region eu-west-1 --name sr2x8pbti0eon1
#
# NOTES:
#   Returns all RDS statistics for all RDS instances in this account unless you specify --name
#
# LICENSE:
#   Peter Hoppe <peter.hoppe.extern@bertelsmann.de>
#   Released under the same terms as Sensu (the MIT license); see LICENSE
#   for details.
#

require 'sensu-plugins-aws'
require 'sensu-plugin/metric/cli'
require 'aws-sdk'
require 'time'

class RDSMetrics < Sensu::Plugin::Metric::CLI::Graphite
  include Common
  option :scheme,
         description: 'Metric naming scheme, text to prepend to metric',
         short: '-s SCHEME',
         long: '--scheme SCHEME'

  option :aws_region,
         short:       '-r AWS_REGION',
         long:        '--aws-region REGION',
         description: 'AWS Region (defaults to us-east-1).',
         default:     ENV['AWS_REGION']

  option :db_instance_id,
         short:       '-i N',
         long:        '--db-instance-id NAME',
         description: 'DB instance identifier'

  option :end_time,
         short:       '-t T',
         long:        '--end-time TIME',
         default:     Time.now,
         proc:        proc { |a| Time.parse a },
         description: 'CloudWatch metric statistics end time'

  option :fetch_age,
         description: 'How long ago to fetch metrics from',
         short: '-f AGE',
         long: '--fetch-age',
         default: 0,
         proc: proc(&:to_i)

  option :period,
         short:       '-p N',
         long:        '--period SECONDS',
         default:     60,
         proc:        proc(&:to_i),
         description: 'CloudWatch metric statistics period'

  option :statistics,
         short:       '-S N',
         long:        '--statistics NAME',
         default:     :average,
         proc:        proc { |a| a.downcase.intern },
         description: 'CloudWatch statistics method'

  def rds
    @rds = Aws::RDS::Client.new
  end

  def cloud_watch
    @cloud_watch = Aws::CloudWatch::Client.new
  end

  def find_db_instance(id)
    db = rds.describe_db_instances.db_instances.detect { |db_instance| db_instance.db_instance_identifier == id }
    unknown 'DB instance not found.' if db.nil?
    db
  end

  def cloud_watch_metric(metric_name, value)
    cloud_watch.get_metric_statistics(
      namespace: 'AWS/RDS',
      metric_name: metric_name,
      dimensions: [
        {
          name: 'DBInstanceIdentifier',
          value: value
        }
      ],
      start_time: config[:end_time] - config[:fetch_age] - config[:period],
      end_time: config[:end_time] - config[:fetch_age],
      statistics: [config[:statistics].to_s.capitalize],
      period: config[:period]
    )
  end

  def run
    statistic_type = {
      'CPUUtilization' => 'Average',
      'DatabaseConnections' => 'Average',
      'FreeStorageSpace' => 'Average',
      'ReadIOPS' => 'Average',
      'ReadLatency' => 'Average',
      'ReadThroughput' => 'Average',
      'WriteIOPS' => 'Average',
      'WriteLatency' => 'Average',
      'WriteThroughput' => 'Average',
      'ReplicaLag' => 'Average',
      'SwapUsage' => 'Average',
      'BinLogDiskUsage' => 'Average',
      'DiskQueueDepth' => 'Average'
    }

    @db_instance  = find_db_instance config[:db_instance_id]
    @message      = "#{config[:db_instance_id]}: "

    result = {}

    rdsname = @db_instance.db_instance_identifier
    full_scheme =
      if config[:scheme].nil?
        rdsname
      else
        config[:scheme] + '.' + rdsname
      end

    statistic_type.each_key do |key, _value|
      r = cloud_watch_metric key, rdsname
      result[full_scheme + '.' + key] = r[:datapoints][0] unless r[:datapoints][0].nil?
    end
    unless result.nil?
      result.each do |key, value|
        output key.downcase.to_s, value.average, value[:timestamp].to_i
      end
    end
    exit
  end
end