sensu-plugins-aws 0.0.1.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|