sensu-plugins-aws 0.0.1.alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +2 -0
- data/CHANGELOG.md +15 -0
- data/LICENSE +22 -0
- data/README.md +125 -0
- data/bin/autoscaling-instance-count-metrics.rb +87 -0
- data/bin/check-dynamodb-capacity.rb +183 -0
- data/bin/check-dynamodb-throttle.rb +177 -0
- data/bin/check-ec2-network.rb +131 -0
- data/bin/check-elb-certs.rb +149 -0
- data/bin/check-elb-health-fog.rb +121 -0
- data/bin/check-elb-health-sdk.rb +124 -0
- data/bin/check-elb-health.rb +122 -0
- data/bin/check-elb-latency.rb +175 -0
- data/bin/check-elb-nodes.rb +145 -0
- data/bin/check-elb-sum-requests.rb +168 -0
- data/bin/check-instance-events.rb +130 -0
- data/bin/check-rds-events.rb +84 -0
- data/bin/check-rds.rb +251 -0
- data/bin/check-redshift-events.rb +120 -0
- data/bin/check-ses-limit.rb +91 -0
- data/bin/check-sqs-messages.rb +107 -0
- data/bin/check_vpc_vpn.py +42 -0
- data/bin/ec2-count-metrics.rb +144 -0
- data/bin/ec2-node.rb +157 -0
- data/bin/elasticache-metrics.rb +200 -0
- data/bin/elb-full-metrics.rb +144 -0
- data/bin/elb-latency-metrics.rb +150 -0
- data/bin/elb-metrics.rb +150 -0
- data/bin/sqs-metrics.rb +84 -0
- data/lib/sensu-plugins-AWS.rb +7 -0
- data.tar.gz.sig +0 -0
- metadata +330 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# ec2-count-metrics
|
|
4
|
+
#
|
|
5
|
+
# DESCRIPTION:
|
|
6
|
+
# This plugin retrives number of EC2 status
|
|
7
|
+
#
|
|
8
|
+
# OUTPUT:
|
|
9
|
+
# plain-text
|
|
10
|
+
#
|
|
11
|
+
# PLATFORMS:
|
|
12
|
+
# Linux
|
|
13
|
+
#
|
|
14
|
+
# DEPENDENCIES:
|
|
15
|
+
# gem: aws-sdk
|
|
16
|
+
# gem: sensu-plugin
|
|
17
|
+
#
|
|
18
|
+
# USAGE:
|
|
19
|
+
# #YELLOW
|
|
20
|
+
#
|
|
21
|
+
# NOTES:
|
|
22
|
+
#
|
|
23
|
+
# LICENSE:
|
|
24
|
+
# Copyright (c) 2014, Tim Smith, tim@cozy.co
|
|
25
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
|
26
|
+
# for details.
|
|
27
|
+
#
|
|
28
|
+
|
|
29
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
|
30
|
+
require 'sensu-plugin/metric/cli'
|
|
31
|
+
require 'aws-sdk'
|
|
32
|
+
|
|
33
|
+
class EC2Metrics < Sensu::Plugin::Metric::CLI::Graphite
|
|
34
|
+
option :scheme,
|
|
35
|
+
description: 'Metric naming scheme, text to prepend to metric',
|
|
36
|
+
short: '-s SCHEME',
|
|
37
|
+
long: '--scheme SCHEME',
|
|
38
|
+
default: 'sensu.aws.ec2'
|
|
39
|
+
|
|
40
|
+
option :aws_access_key,
|
|
41
|
+
short: '-a AWS_ACCESS_KEY',
|
|
42
|
+
long: '--aws-access-key AWS_ACCESS_KEY',
|
|
43
|
+
description: "AWS Access Key. Either set ENV['AWS_ACCESS_KEY_ID'] or provide it as an option"
|
|
44
|
+
|
|
45
|
+
option :aws_secret_access_key,
|
|
46
|
+
short: '-k AWS_SECRET_ACCESS_KEY',
|
|
47
|
+
long: '--aws-secret-access-key AWS_SECRET_ACCESS_KEY',
|
|
48
|
+
description: "AWS Secret Access Key. Either set ENV['AWS_SECRET_ACCESS_KEY'] or provide it as an option"
|
|
49
|
+
|
|
50
|
+
option :aws_region,
|
|
51
|
+
short: '-r AWS_REGION',
|
|
52
|
+
long: '--aws-region REGION',
|
|
53
|
+
description: 'AWS Region (such as us-east-1).',
|
|
54
|
+
default: 'us-east-1'
|
|
55
|
+
|
|
56
|
+
option :type,
|
|
57
|
+
short: '-t METRIC type',
|
|
58
|
+
long: '--type METRIC type',
|
|
59
|
+
description: 'Count by type: status, instance',
|
|
60
|
+
default: 'instance'
|
|
61
|
+
|
|
62
|
+
def aws_config
|
|
63
|
+
hash = {}
|
|
64
|
+
hash.update access_key_id: config[:access_key_id], secret_access_key: config[:secret_access_key] if config[:access_key_id] && config[:secret_access_key]
|
|
65
|
+
hash.update region: config[:aws_region]
|
|
66
|
+
hash
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def run
|
|
70
|
+
begin
|
|
71
|
+
|
|
72
|
+
client = AWS::EC2::Client.new aws_config
|
|
73
|
+
|
|
74
|
+
def by_instances_status(client)
|
|
75
|
+
if config[:scheme] == 'sensu.aws.ec2'
|
|
76
|
+
config[:scheme] += '.count'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
options = { include_all_instances: true }
|
|
80
|
+
data = client.describe_instance_status(options)
|
|
81
|
+
|
|
82
|
+
total = data[:instance_status_set].count
|
|
83
|
+
status = {}
|
|
84
|
+
|
|
85
|
+
unless total.nil?
|
|
86
|
+
data[:instance_status_set].each do |value|
|
|
87
|
+
stat = value[:instance_state][:name]
|
|
88
|
+
if status[stat].nil?
|
|
89
|
+
status[stat] = 1
|
|
90
|
+
else
|
|
91
|
+
status[stat] = status[stat] + 1
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
unless data.nil?
|
|
97
|
+
# We only return data when we have some to return
|
|
98
|
+
output config[:scheme] + '.total', total
|
|
99
|
+
status.each do |name, count|
|
|
100
|
+
output config[:scheme] + ".#{name}", count
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def by_instances_type(client)
|
|
106
|
+
if config[:scheme] == 'sensu.aws.ec2'
|
|
107
|
+
config[:scheme] += '.types'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
data = {}
|
|
111
|
+
|
|
112
|
+
instances = client.describe_instances
|
|
113
|
+
instances[:reservation_set].each do |i|
|
|
114
|
+
i[:instances_set].each do |instance|
|
|
115
|
+
type = instance[:instance_type]
|
|
116
|
+
if data[type].nil?
|
|
117
|
+
data[type] = 1
|
|
118
|
+
else
|
|
119
|
+
data[type] = data[type] + 1
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
unless data.nil?
|
|
125
|
+
# We only return data when we have some to return
|
|
126
|
+
data.each do |name, count|
|
|
127
|
+
output config[:scheme] + ".#{name}", count
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if config[:type] == 'instance'
|
|
133
|
+
by_instances_type(client)
|
|
134
|
+
elsif config[:type] == 'status'
|
|
135
|
+
by_instances_status(client)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
rescue => e
|
|
139
|
+
puts "Error: exception: #{e}"
|
|
140
|
+
critical
|
|
141
|
+
end
|
|
142
|
+
ok
|
|
143
|
+
end
|
|
144
|
+
end
|
data/bin/ec2-node.rb
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# CHANGELOG:
|
|
4
|
+
# * 0.4.0:
|
|
5
|
+
# - Adds ability to specify a list of states an individual client can have in
|
|
6
|
+
# EC2. If none is specified, it filters out 'terminated' and 'stopped'
|
|
7
|
+
# instances by default.
|
|
8
|
+
# - Updates how we are "puts"-ing to the log.
|
|
9
|
+
# * 0.3.0:
|
|
10
|
+
# - Updates handler to additionally filter stopped instances.
|
|
11
|
+
# * 0.2.1:
|
|
12
|
+
# - Updates requested configuration snippets so they'll be redacted by
|
|
13
|
+
# default.
|
|
14
|
+
# * 0.2.0:
|
|
15
|
+
# - Renames handler from chef_ec2_node to ec2_node
|
|
16
|
+
# - Removes Chef-related stuff from handler
|
|
17
|
+
# - Updates documentation
|
|
18
|
+
# * 0.1.0:
|
|
19
|
+
# - Initial release
|
|
20
|
+
#
|
|
21
|
+
# This handler deletes a Sensu client if it's been stopped or terminated in EC2.
|
|
22
|
+
# Optionally, you may specify a client attribute `ec2_states`, a list of valid
|
|
23
|
+
# states an instance may have.
|
|
24
|
+
#
|
|
25
|
+
# NOTE: The implementation for correlating Sensu clients to EC2 instances may
|
|
26
|
+
# need to be modified to fit your organization. The current implementation
|
|
27
|
+
# assumes that Sensu clients' names are the same as their instance IDs in EC2.
|
|
28
|
+
# If this is not the case, you can either sub-class this handler and override
|
|
29
|
+
# `ec2_node_exists?` in your own organization-specific handler, or modify this
|
|
30
|
+
# handler to suit your needs.
|
|
31
|
+
#
|
|
32
|
+
# Requires the following Rubygems (`gem install $GEM`):
|
|
33
|
+
# - sensu-plugin
|
|
34
|
+
# - fog
|
|
35
|
+
#
|
|
36
|
+
# Requires a Sensu configuration snippet:
|
|
37
|
+
# {
|
|
38
|
+
# "aws": {
|
|
39
|
+
# "access_key": "adsafdafda",
|
|
40
|
+
# "secret_key": "qwuieohajladsafhj23nm",
|
|
41
|
+
# "region": "us-east-1c"
|
|
42
|
+
# }
|
|
43
|
+
# }
|
|
44
|
+
#
|
|
45
|
+
# Or you can set the following environment variables:
|
|
46
|
+
# - AWS_ACCESS_KEY_ID
|
|
47
|
+
# - AWS_SECRET_ACCESS_KEY
|
|
48
|
+
# - EC2_REGION
|
|
49
|
+
#
|
|
50
|
+
#
|
|
51
|
+
# To use, you can set it as the keepalive handler for a client:
|
|
52
|
+
# {
|
|
53
|
+
# "client": {
|
|
54
|
+
# "name": "i-424242",
|
|
55
|
+
# "address": "127.0.0.1",
|
|
56
|
+
# "keepalive": {
|
|
57
|
+
# "handler": "ec2_node"
|
|
58
|
+
# },
|
|
59
|
+
# "subscriptions": ["all"]
|
|
60
|
+
# }
|
|
61
|
+
# }
|
|
62
|
+
#
|
|
63
|
+
# You can also use this handler with a filter:
|
|
64
|
+
# {
|
|
65
|
+
# "filters": {
|
|
66
|
+
# "ghost_nodes": {
|
|
67
|
+
# "attributes": {
|
|
68
|
+
# "check": {
|
|
69
|
+
# "name": "keepalive",
|
|
70
|
+
# "status": 2
|
|
71
|
+
# },
|
|
72
|
+
# "occurences": "eval: value > 2"
|
|
73
|
+
# }
|
|
74
|
+
# }
|
|
75
|
+
# },
|
|
76
|
+
# "handlers": {
|
|
77
|
+
# "ec2_node": {
|
|
78
|
+
# "type": "pipe",
|
|
79
|
+
# "command": "/etc/sensu/handlers/ec2_node.rb",
|
|
80
|
+
# "severities": ["warning","critical"],
|
|
81
|
+
# "filter": "ghost_nodes"
|
|
82
|
+
# }
|
|
83
|
+
# }
|
|
84
|
+
# }
|
|
85
|
+
#
|
|
86
|
+
# Copyleft 2013 Yet Another Clever Name
|
|
87
|
+
#
|
|
88
|
+
# Based off of the `chef_node` handler by Heavy Water Operations, LLC
|
|
89
|
+
#
|
|
90
|
+
# Released under the same terms as Sensu (the MIT license); see
|
|
91
|
+
# LICENSE for details
|
|
92
|
+
|
|
93
|
+
require 'timeout'
|
|
94
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
|
95
|
+
require 'sensu-handler'
|
|
96
|
+
require 'fog'
|
|
97
|
+
|
|
98
|
+
class Ec2Node < Sensu::Handler
|
|
99
|
+
def filter; end
|
|
100
|
+
|
|
101
|
+
def handle
|
|
102
|
+
# #YELLOW
|
|
103
|
+
unless ec2_node_exists? # rubocop:disable UnlessElse
|
|
104
|
+
delete_sensu_client!
|
|
105
|
+
else
|
|
106
|
+
puts "[EC2 Node] #{@event['client']['name']} appears to exist in EC2"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def delete_sensu_client!
|
|
111
|
+
response = api_request(:DELETE, '/clients/' + @event['client']['name']).code
|
|
112
|
+
deletion_status(response)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def ec2_node_exists?
|
|
116
|
+
states = acquire_valid_states
|
|
117
|
+
filtered_instances = ec2.servers.select { |s| states.include?(s.state) }
|
|
118
|
+
instance_ids = filtered_instances.map(&:id)
|
|
119
|
+
instance_ids.each do |id|
|
|
120
|
+
return true if id == @event['client']['name']
|
|
121
|
+
end
|
|
122
|
+
false # no match found, node doesn't exist
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def ec2
|
|
126
|
+
@ec2 ||= begin
|
|
127
|
+
key = settings['aws']['access_key'] || ENV['AWS_ACCESS_KEY_ID']
|
|
128
|
+
secret = settings['aws']['secret_key'] || ENV['AWS_SECRET_ACCESS_KEY']
|
|
129
|
+
region = settings['aws']['region'] || ENV['EC2_REGION']
|
|
130
|
+
Fog::Compute.new(provider: 'AWS',
|
|
131
|
+
aws_access_key_id: key,
|
|
132
|
+
aws_secret_access_key: secret,
|
|
133
|
+
region: region)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def deletion_status(code)
|
|
138
|
+
case code
|
|
139
|
+
when '202'
|
|
140
|
+
puts "[EC2 Node] 202: Successfully deleted Sensu client: #{node}"
|
|
141
|
+
when '404'
|
|
142
|
+
puts "[EC2 Node] 404: Unable to delete #{node}, doesn't exist!"
|
|
143
|
+
when '500'
|
|
144
|
+
puts "[EC2 Node] 500: Miscellaneous error when deleting #{node}"
|
|
145
|
+
else
|
|
146
|
+
puts "[EC2 Node] #{res}: Completely unsure of what happened!"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def acquire_valid_states
|
|
151
|
+
if @event['client'].key?('ec2_states')
|
|
152
|
+
return @event['client']['ec2_states']
|
|
153
|
+
else
|
|
154
|
+
return ['running']
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# elasticache-metrics
|
|
4
|
+
#
|
|
5
|
+
# DESCRIPTION:
|
|
6
|
+
# Fetch Elasticache metrics from CloudWatch
|
|
7
|
+
#
|
|
8
|
+
# OUTPUT:
|
|
9
|
+
# metric-data
|
|
10
|
+
#
|
|
11
|
+
# PLATFORMS:
|
|
12
|
+
# Linux
|
|
13
|
+
#
|
|
14
|
+
# DEPENDENCIES:
|
|
15
|
+
# gem: aws-sdk
|
|
16
|
+
# gem: sensu-plugin
|
|
17
|
+
#
|
|
18
|
+
# needs example command
|
|
19
|
+
# USAGE:
|
|
20
|
+
# #YELLOW
|
|
21
|
+
|
|
22
|
+
# NOTES:
|
|
23
|
+
# Redis: http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CacheMetrics.Redis.html
|
|
24
|
+
# Memcached: http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CacheMetrics.Memcached.html
|
|
25
|
+
#
|
|
26
|
+
# By default fetches all available statistics from one minute ago. You may need to fetch further back than this;
|
|
27
|
+
#
|
|
28
|
+
# LICENSE:
|
|
29
|
+
# Copyright 2014 Yann Verry
|
|
30
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
|
31
|
+
# for details.
|
|
32
|
+
#
|
|
33
|
+
|
|
34
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
|
35
|
+
require 'sensu-plugin/metric/cli'
|
|
36
|
+
require 'aws-sdk'
|
|
37
|
+
|
|
38
|
+
class ElastiCacheMetrics < Sensu::Plugin::Metric::CLI::Graphite
|
|
39
|
+
option :cacheclusterid,
|
|
40
|
+
description: 'Name of the Cache Cluster',
|
|
41
|
+
short: '-n ELASTICACHE_NAME',
|
|
42
|
+
long: '--name ELASTICACHE_NAME',
|
|
43
|
+
required: true
|
|
44
|
+
|
|
45
|
+
option :cachenodeid,
|
|
46
|
+
description: 'Cache Node ID',
|
|
47
|
+
short: '-i CACHE_NODE_ID',
|
|
48
|
+
long: '--cache-node-id CACHE_NODE_ID',
|
|
49
|
+
default: '0001'
|
|
50
|
+
|
|
51
|
+
option :elasticachetype,
|
|
52
|
+
description: 'Elasticache type redis or memcached',
|
|
53
|
+
short: '-c TYPE',
|
|
54
|
+
long: '--cachetype TYPE',
|
|
55
|
+
required: true
|
|
56
|
+
|
|
57
|
+
option :scheme,
|
|
58
|
+
description: 'Metric naming scheme, text to prepend to metric',
|
|
59
|
+
short: '-s SCHEME',
|
|
60
|
+
long: '--scheme SCHEME',
|
|
61
|
+
default: ''
|
|
62
|
+
|
|
63
|
+
option :fetch_age,
|
|
64
|
+
description: 'How long ago to fetch metrics for',
|
|
65
|
+
short: '-f AGE',
|
|
66
|
+
long: '--fetch_age',
|
|
67
|
+
default: 60,
|
|
68
|
+
proc: proc(&:to_i)
|
|
69
|
+
|
|
70
|
+
option :aws_access_key,
|
|
71
|
+
short: '-a AWS_ACCESS_KEY',
|
|
72
|
+
long: '--aws-access-key AWS_ACCESS_KEY',
|
|
73
|
+
description: "AWS Access Key. Either set ENV['AWS_ACCESS_KEY_ID'] or provide it as an option"
|
|
74
|
+
|
|
75
|
+
option :aws_secret_access_key,
|
|
76
|
+
short: '-k AWS_SECRET_ACCESS_KEY',
|
|
77
|
+
long: '--aws-secret-access-key AWS_SECRET_ACCESS_KEY',
|
|
78
|
+
description: "AWS Secret Access Key. Either set ENV['AWS_SECRET_ACCESS_KEY'] or provide it as an option"
|
|
79
|
+
|
|
80
|
+
option :aws_region,
|
|
81
|
+
short: '-r AWS_REGION',
|
|
82
|
+
long: '--aws-region REGION',
|
|
83
|
+
description: 'AWS Region (such as us-east-1).',
|
|
84
|
+
default: 'us-east-1'
|
|
85
|
+
|
|
86
|
+
def aws_config
|
|
87
|
+
hash = {}
|
|
88
|
+
hash.update access_key_id: config[:access_key_id], secret_access_key: config[:secret_access_key] if config[:access_key_id] && config[:secret_access_key]
|
|
89
|
+
hash.update region: config[:aws_region]
|
|
90
|
+
hash
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def run
|
|
94
|
+
if config[:scheme] == ''
|
|
95
|
+
graphitepath = "#{config[:elasticachename]}.#{config[:metric].downcase}"
|
|
96
|
+
else
|
|
97
|
+
graphitepath = config[:scheme]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
statistic_type = {
|
|
101
|
+
'redis' => {
|
|
102
|
+
'CPUUtilization' => 'Percent',
|
|
103
|
+
'SwapUsage' => 'Bytes',
|
|
104
|
+
'FreeableMemory' => 'Bytes',
|
|
105
|
+
'NetworkBytesIn' => 'Bytes',
|
|
106
|
+
'NetworkBytesOut' => 'Bytes',
|
|
107
|
+
'GetTypeCmds' => 'Count',
|
|
108
|
+
'SetTypeCmds' => 'Count',
|
|
109
|
+
'KeyBasedCmds' => 'Count',
|
|
110
|
+
'StringBasedCmds' => 'Count',
|
|
111
|
+
'HashBasedCmds' => 'Count',
|
|
112
|
+
'ListBasedCmds' => 'Count',
|
|
113
|
+
'SetBasedCmds' => 'Count',
|
|
114
|
+
'SortedSetBasedCmds' => 'Count',
|
|
115
|
+
'CurrItems' => 'Count'
|
|
116
|
+
},
|
|
117
|
+
'memcached' => {
|
|
118
|
+
'CPUUtilization' => 'Percent',
|
|
119
|
+
'SwapUsage' => 'Bytes',
|
|
120
|
+
'FreeableMemory' => 'Bytes',
|
|
121
|
+
'NetworkBytesIn' => 'Bytes',
|
|
122
|
+
'NetworkBytesOut' => 'Bytes',
|
|
123
|
+
'BytesUsedForCacheItems' => 'Bytes',
|
|
124
|
+
'BytesReadIntoMemcached' => 'Bytes',
|
|
125
|
+
'BytesWrittenOutFromMemcached' => 'Bytes',
|
|
126
|
+
'CasBadval' => 'Count',
|
|
127
|
+
'CasHits' => 'Count',
|
|
128
|
+
'CasMisses' => 'Count',
|
|
129
|
+
'CmdFlush' => 'Count',
|
|
130
|
+
'CmdGet' => 'Count',
|
|
131
|
+
'CmdSet' => 'Count',
|
|
132
|
+
'CurrConnections' => 'Count',
|
|
133
|
+
'CurrItems' => 'Count',
|
|
134
|
+
'DecrHits' => 'Count',
|
|
135
|
+
'DecrMisses' => 'Count',
|
|
136
|
+
'DeleteHits' => 'Count',
|
|
137
|
+
'DeleteMisses' => 'Count',
|
|
138
|
+
'Evictions' => 'Count',
|
|
139
|
+
'GetHits' => 'Count',
|
|
140
|
+
'GetMisses' => 'Count',
|
|
141
|
+
'IncrHits' => 'Count',
|
|
142
|
+
'IncrMisses' => 'Count',
|
|
143
|
+
'Reclaimed' => 'Count',
|
|
144
|
+
'BytesUsedForHash' => 'Bytes',
|
|
145
|
+
'CmdConfigGet' => 'Count',
|
|
146
|
+
'CmdConfigSet' => 'Count',
|
|
147
|
+
'CmdTouch' => 'Count',
|
|
148
|
+
'CurrConfig' => 'Count',
|
|
149
|
+
'EvictedUnfetched' => 'Count',
|
|
150
|
+
'ExpiredUnfetched' => 'Count',
|
|
151
|
+
'SlabsMoved' => 'Count',
|
|
152
|
+
'TouchHits' => 'Count',
|
|
153
|
+
'TouchMisses' => 'Count',
|
|
154
|
+
'NewConnections' => 'Count',
|
|
155
|
+
'NewItems' => 'Count',
|
|
156
|
+
'UnusedMemory' => 'Bytes'
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
begin
|
|
161
|
+
et = Time.now - config[:fetch_age]
|
|
162
|
+
st = et - 60
|
|
163
|
+
|
|
164
|
+
cw = AWS::CloudWatch::Client.new aws_config
|
|
165
|
+
|
|
166
|
+
# define all options
|
|
167
|
+
options = {
|
|
168
|
+
'namespace' => 'AWS/ElastiCache',
|
|
169
|
+
'metric_name' => config[:metric],
|
|
170
|
+
'dimensions' => [
|
|
171
|
+
{ 'name' => 'CacheClusterId', 'value' => config[:cacheclusterid] }
|
|
172
|
+
],
|
|
173
|
+
'start_time' => st.iso8601,
|
|
174
|
+
'end_time' => et.iso8601,
|
|
175
|
+
'period' => 60,
|
|
176
|
+
'statistics' => ['Average']
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
result = {}
|
|
180
|
+
|
|
181
|
+
# Fetch all metrics by elasticachetype (redis or memcached).
|
|
182
|
+
statistic_type[config[:elasticachetype]].each do |m|
|
|
183
|
+
options['metric_name'] = m[0] # override metric
|
|
184
|
+
r = cw.get_metric_statistics(options)
|
|
185
|
+
result[m[0]] = r[:datapoints][0] unless r[:datapoints][0].nil?
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
unless result.nil?
|
|
189
|
+
result.each do |name, d|
|
|
190
|
+
# We only return data when we have some to return
|
|
191
|
+
output graphitepath + '.' + name.downcase, d[:average], d[:timestamp].to_i
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
rescue => e
|
|
195
|
+
puts "Error: exception: #{e}"
|
|
196
|
+
critical
|
|
197
|
+
end
|
|
198
|
+
ok
|
|
199
|
+
end
|
|
200
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# elb-full-metrics
|
|
4
|
+
#
|
|
5
|
+
# DESCRIPTION:
|
|
6
|
+
# Gets latency metrics from CloudWatch and puts them in Graphite for longer term storage
|
|
7
|
+
#
|
|
8
|
+
# OUTPUT:
|
|
9
|
+
# metric-data
|
|
10
|
+
#
|
|
11
|
+
# PLATFORMS:
|
|
12
|
+
# Linux
|
|
13
|
+
#
|
|
14
|
+
# DEPENDENCIES:
|
|
15
|
+
# gem: sensu-plugin
|
|
16
|
+
#
|
|
17
|
+
# USAGE:
|
|
18
|
+
# #YELLOW
|
|
19
|
+
#
|
|
20
|
+
# NOTES:
|
|
21
|
+
# Returns latency statistics by default. You can specify any valid ELB metric type, see
|
|
22
|
+
# http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html#elb-metricscollected
|
|
23
|
+
#
|
|
24
|
+
# By default fetches statistics from one minute ago. You may need to fetch further back than this;
|
|
25
|
+
# high traffic ELBs can sometimes experience statistic delays of up to 10 minutes. If you experience this,
|
|
26
|
+
# raising a ticket with AWS support should get the problem resolved.
|
|
27
|
+
# As a workaround you can use eg -f 300 to fetch data from 5 minutes ago.
|
|
28
|
+
#
|
|
29
|
+
# LICENSE:
|
|
30
|
+
# Copyright 2013 Bashton Ltd http://www.bashton.com/
|
|
31
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
|
32
|
+
# for details.
|
|
33
|
+
#
|
|
34
|
+
|
|
35
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
|
36
|
+
require 'sensu-plugin/metric/cli'
|
|
37
|
+
require 'aws-sdk'
|
|
38
|
+
|
|
39
|
+
class ELBMetrics < Sensu::Plugin::Metric::CLI::Graphite
|
|
40
|
+
option :elbname,
|
|
41
|
+
description: 'Name of the Elastic Load Balancer',
|
|
42
|
+
short: '-n ELB_NAME',
|
|
43
|
+
long: '--name ELB_NAME'
|
|
44
|
+
|
|
45
|
+
option :scheme,
|
|
46
|
+
description: 'Metric naming scheme, text to prepend to metric',
|
|
47
|
+
short: '-s SCHEME',
|
|
48
|
+
long: '--scheme SCHEME',
|
|
49
|
+
default: ''
|
|
50
|
+
|
|
51
|
+
option :fetch_age,
|
|
52
|
+
description: 'How long ago to fetch metrics for',
|
|
53
|
+
short: '-f AGE',
|
|
54
|
+
long: '--fetch_age',
|
|
55
|
+
default: 60,
|
|
56
|
+
proc: proc(&:to_i)
|
|
57
|
+
|
|
58
|
+
option :aws_access_key,
|
|
59
|
+
short: '-a AWS_ACCESS_KEY',
|
|
60
|
+
long: '--aws-access-key AWS_ACCESS_KEY',
|
|
61
|
+
description: "AWS Access Key. Either set ENV['AWS_ACCESS_KEY'] or provide it as an option",
|
|
62
|
+
required: true,
|
|
63
|
+
default: ENV['AWS_ACCESS_KEY']
|
|
64
|
+
|
|
65
|
+
option :aws_secret_access_key,
|
|
66
|
+
short: '-k AWS_SECRET_KEY',
|
|
67
|
+
long: '--aws-secret-access-key AWS_SECRET_KEY',
|
|
68
|
+
description: "AWS Secret Access Key. Either set ENV['AWS_SECRET_KEY'] or provide it as an option",
|
|
69
|
+
required: true,
|
|
70
|
+
default: ENV['AWS_SECRET_KEY']
|
|
71
|
+
|
|
72
|
+
option :aws_region,
|
|
73
|
+
short: '-r AWS_REGION',
|
|
74
|
+
long: '--aws-region REGION',
|
|
75
|
+
description: 'AWS Region (such as eu-west-1).',
|
|
76
|
+
default: 'us-east-1'
|
|
77
|
+
|
|
78
|
+
def aws_config
|
|
79
|
+
hash = {}
|
|
80
|
+
hash.update access_key_id: config[:access_key_id], secret_access_key: config[:secret_access_key] if config[:access_key_id] && config[:secret_access_key]
|
|
81
|
+
hash.update region: config[:aws_region]
|
|
82
|
+
hash
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def run
|
|
86
|
+
statistic_type = {
|
|
87
|
+
'Latency' => 'Average',
|
|
88
|
+
'RequestCount' => 'Sum',
|
|
89
|
+
'UnHealthyHostCount' => 'Average',
|
|
90
|
+
'HealthyHostCount' => 'Average',
|
|
91
|
+
'HTTPCode_Backend_2XX' => 'Sum',
|
|
92
|
+
'HTTPCode_Backend_4XX' => 'Sum',
|
|
93
|
+
'HTTPCode_Backend_5XX' => 'Sum',
|
|
94
|
+
'HTTPCode_ELB_4XX' => 'Sum',
|
|
95
|
+
'HTTPCode_ELB_5XX' => 'Sum'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
begin
|
|
99
|
+
et = Time.now - config[:fetch_age]
|
|
100
|
+
st = et - 60
|
|
101
|
+
|
|
102
|
+
cw = AWS::CloudWatch::Client.new aws_config
|
|
103
|
+
|
|
104
|
+
options = {
|
|
105
|
+
'namespace' => 'AWS/ELB',
|
|
106
|
+
'dimensions' => [
|
|
107
|
+
{
|
|
108
|
+
'name' => 'LoadBalancerName',
|
|
109
|
+
'value' => config[:elbname]
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
'start_time' => st.iso8601,
|
|
113
|
+
'end_time' => et.iso8601,
|
|
114
|
+
'period' => 60
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
result = {}
|
|
118
|
+
graphitepath = config[:scheme]
|
|
119
|
+
|
|
120
|
+
config[:elbname].split(' ').each do |elbname|
|
|
121
|
+
statistic_type.each do |key, value|
|
|
122
|
+
if config[:scheme] == ''
|
|
123
|
+
graphitepath = "#{config[:elbname]}.#{key.downcase}"
|
|
124
|
+
end
|
|
125
|
+
options['metric_name'] = key
|
|
126
|
+
options['dimensions'][0]['value'] = elbname
|
|
127
|
+
options['statistics'] = [value]
|
|
128
|
+
r = cw.get_metric_statistics(options)
|
|
129
|
+
result[key] = r[:datapoints][0] unless r[:datapoints][0].nil?
|
|
130
|
+
end
|
|
131
|
+
unless result.nil?
|
|
132
|
+
# We only return data when we have some to return
|
|
133
|
+
result.each do |key, value|
|
|
134
|
+
puts key, value
|
|
135
|
+
output graphitepath + ".#{key}", value.to_a.last[1], value[:timestamp].to_i
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
rescue => e
|
|
140
|
+
critical "Error: exception: #{e}"
|
|
141
|
+
end
|
|
142
|
+
ok
|
|
143
|
+
end
|
|
144
|
+
end
|