riemann-aws 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4e51ebb1396ffd7f7f8f3b7a5dad6079c4d91729
4
+ data.tar.gz: cb449ca629c9a39103869733739be2cd19c5e817
5
+ SHA512:
6
+ metadata.gz: 466cd5dd681b6f3a3c91b7bfb2120eb5753da93c23f5230b4e44ddaf6fe41b3f6ddaf80d897e7b60a702ddf31bf0df6cc6266b9c85e0b0c4d576092d2ca6c9e4
7
+ data.tar.gz: ff6dfb5aadf7b91c44d745eb4ff667eee19bacfef9854d85400ec30598c2bc2c5528adb4e25e25bafcb77a29208522452dd2b1b2018c6b1f6526599857078dd5
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Riemann AWS tools
2
+
3
+ Gathers various AWS services statistics and submits them to Riemann.
4
+
5
+ ## Getting started
6
+
7
+ ```
8
+ gem install riemann-aws
9
+ ```
10
+
11
+ ## AWS Commands
12
+
13
+
14
+ ### Riemann AWS Billing
15
+
16
+ ```
17
+ riemann-aws-billing --help
18
+ ```
19
+
20
+ ### Riemann AWS RDS Status
21
+
22
+ ```
23
+ riemann-aws-rds-status --help
24
+ ```
25
+
26
+ ### Riemann AWS SQS Satus
27
+
28
+ ```
29
+ riemann-aws-sqs-status --help
30
+ ```
31
+
32
+ ### Riemann AWS Status
33
+
34
+ ```
35
+ riemann-aws-status --help
36
+ ```
37
+
38
+ ### Riemann ELB Metrics
39
+
40
+ ```
41
+ riemann-elb-metrics --help
42
+ ```
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riemann/tools'
4
+
5
+ $0 = __FILE__
6
+
7
+ class Riemann::Tools::AWSBilling
8
+ include Riemann::Tools
9
+ require 'fog'
10
+
11
+ opt :fog_credentials_file, "Fog credentials file", :type => String
12
+ opt :fog_credential, "Fog credentials to use", :type => String
13
+
14
+ opt :access_key, "AWS access key", :type => String
15
+ opt :secret_key, "Secret access key", :type => String
16
+ opt :services, "AWS services: AmazonEC2 AmazonS3 AWSDataTransfer", :type => :strings, :multi => true, :default => ["AmazonEC2", "AmazonS3", "AWSDataTransfer"]
17
+
18
+ opt :time_start, "Start time in seconds of the metrics period (2hrs ago default)", :type => Integer, :default => 7200
19
+ opt :time_end, "End time in seconds of the metrics period ", :type => Integer, :default => 60
20
+
21
+
22
+ def initialize
23
+ if options[:fog_credentials_file]
24
+ Fog.credentials_path = opts[:fog_credentials_file]
25
+ Fog.credential = opts[:fog_credential].to_sym
26
+ @cloudwatch = Fog::AWS::CloudWatch.new
27
+ else
28
+ @cloudwatch = Fog::AWS::CloudWatch.new(:aws_secret_access_key => opts[:secret_key], :aws_access_key_id => opts[:access_key])
29
+ @start_time = (Time.now.utc - opts[:time_start]).iso8601
30
+ @end_time = (Time.now.utc - opts[:time_end]).iso8601
31
+ end
32
+ end
33
+
34
+ def tick
35
+ opts[:services].each do |service|
36
+ data = @cloudwatch.get_metric_statistics({
37
+ 'Statistics' => ["Maximum"],
38
+ 'StartTime' => @start_time,
39
+ 'EndTime' => @end_time,
40
+ 'Period' => 3600,
41
+ 'Unit' => "None",
42
+ 'MetricName' => "EstimatedCharges",
43
+ 'Namespace' => "AWS/Billing",
44
+ 'Dimensions' => [
45
+ {
46
+ 'Name' => "ServiceName",
47
+ 'Value' => service
48
+ },
49
+ {
50
+ 'Name' => "Currency",
51
+ 'Value' => "USD"
52
+ }
53
+ ]
54
+ }).body['GetMetricStatisticsResult']['Datapoints']
55
+
56
+
57
+ data.each do |metrics|
58
+ name = "AWScloudwatch.Billing." + service
59
+ value = metrics["Maximum"]
60
+ timestamp = metrics["Timestamp"].to_i
61
+
62
+ event = {
63
+ host: nil,
64
+ service: name,
65
+ time: timestamp,
66
+ description: "AWS Estimate Charges for #{service}",
67
+ tags: ["aws_billing"],
68
+ state: "ok",
69
+ metric: value
70
+ }
71
+
72
+ report event
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ Riemann::Tools::AWSBilling.run
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riemann/tools'
4
+
5
+ $0 = __FILE__ # Let's not expose our AWS keys in the process list
6
+
7
+ class Riemann::Tools::AWS
8
+ include Riemann::Tools
9
+ require 'fog'
10
+ require 'date'
11
+ require 'time'
12
+ require 'json'
13
+
14
+ opt :access_key, "AWS access key", :type => String
15
+ opt :secret_key, "Secret access key", :type => String
16
+ opt :region, "AWS region", :type => String, :default => 'eu-west-1'
17
+ opt :dbinstance_identifier, "DBInstanceIdentifier", :type => String
18
+ def initialize
19
+ abort "FATAL: specify a DB instance name, see --help for usage" unless opts[:dbinstance_identifier]
20
+ @cloudwatch = Fog::AWS::CloudWatch.new(:aws_access_key_id => opts[:access_key],
21
+ :aws_secret_access_key => opts[:secret_key],
22
+ :region => opts[:region])
23
+ end
24
+
25
+ def tick
26
+ time = Time.new
27
+ ['DatabaseConnections', 'FreeableMemory', 'FreeStorageSpace', 'NetworkReceiveThroughput', 'NetworkTransmitThroughput', 'ReadThroughput', 'CPUUtilization'].each do |metric|
28
+ result = @cloudwatch.get_metric_statistics({"Namespace" => 'AWS/RDS', "MetricName" => "#{metric}", "Statistics" => 'Average', "Dimensions" => [{"Name" => "DBInstanceIdentifier", "Value" => "#{opts[:dbinstance_identifier]}"}], "StartTime" => (time-120).to_time.iso8601, "EndTime" => time.to_time.iso8601, "Period" => 60})
29
+ metricsResult = result.data[:body]['GetMetricStatisticsResult']
30
+ puts JSON.dump(metricsResult)
31
+ if (metricsResult['Datapoints'].length>0)
32
+ datapoint = metricsResult['Datapoints'][0]
33
+ ev = {:metric => datapoint['Average'],
34
+ :service => "#{opts[:dbinstance_identifier]}.#{metric} (#{datapoint['Unit']})",
35
+ :description => JSON.dump(metricsResult),
36
+ :state => "ok",
37
+ :ttl => 300}
38
+
39
+
40
+ report ev
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+
47
+ Riemann::Tools::AWS.run
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riemann/tools'
4
+
5
+ $0 = __FILE__ # Let's not expose our AWS keys in the process list
6
+
7
+ class Riemann::Tools::AWS
8
+ include Riemann::Tools
9
+ require 'fog'
10
+
11
+ opt :access_key, "AWS access key", :type => String
12
+ opt :secret_key, "Secret access key", :type => String
13
+ opt :region, "AWS region", :type => String, :default => 'us-east-1'
14
+ opt :queue, "SQS Queue name", :type => String
15
+ def initialize
16
+ @sqs = Fog::AWS::SQS.new(:aws_access_key_id => opts[:access_key],
17
+ :aws_secret_access_key => opts[:secret_key],
18
+ :region => opts[:region])
19
+ response = @sqs.list_queues({'QueueNamePrefix' => opts[:queue]})
20
+ @queue_url = response[:body]['QueueUrls'].first
21
+ end
22
+
23
+ def tick
24
+ response = @sqs.get_queue_attributes(@queue_url, 'All')
25
+ ['ApproximateNumberOfMessages', 'ApproximateNumberOfMessagesNotVisible'].each do |attr|
26
+ msg = {
27
+ metric: response[:body]['Attributes'][attr],
28
+ service: "#{opts[:queue]} #{attr}",
29
+ state: 'ok'
30
+ }
31
+ report msg
32
+ end
33
+ end
34
+ end
35
+
36
+ Riemann::Tools::AWS.run
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riemann/tools'
4
+
5
+ $0 = __FILE__ # Let's not expose our AWS keys in the process list
6
+
7
+ class Riemann::Tools::AWS
8
+ include Riemann::Tools
9
+ require 'fog'
10
+ require 'date'
11
+
12
+ opt :access_key, "AWS access key", :type => String
13
+ opt :secret_key, "Secret access key", :type => String
14
+ opt :region, "AWS region", :type => String, :default => 'eu-west-1'
15
+
16
+ opt :retirement_critical, "Number of days before retirement. Defaults to 2", :default => 2
17
+ opt :event_warning, "Number of days before event. Defaults to nil (i.e. when the event appears)", :default => nil
18
+
19
+ def initialize
20
+ @compute = Fog::Compute.new(:aws_access_key_id => opts[:access_key],
21
+ :aws_secret_access_key => opts[:secret_key],
22
+ :region => opts[:region],
23
+ :provider => 'AWS')
24
+ end
25
+
26
+ def tick
27
+ instance_status = @compute.describe_instance_status.body["instanceStatusSet"]
28
+ status = instance_status.inject({}) do |acc,i|
29
+ acc[i.delete("instanceId")] = i
30
+ acc
31
+ end
32
+
33
+ hosts = @compute.servers.select { |s| s.state == "running" }
34
+ inject([status, {}]) do |(status, acc), host|
35
+ acc[host.private_dns_name] = status.delete(host.id); [status, acc]
36
+ end[1]
37
+
38
+ hosts.each do |host, status|
39
+ status['eventsSet'].each do |event|
40
+ before, after = ['notBefore', 'notAfter'].map { |k| Date.parse event[k].to_s if event[k] }
41
+
42
+ ev = {:host => host,
43
+ :service => "aws_instance_status",
44
+ :description => "#{event['code']}\n\nstart #{event['notBefore']}\nend #{event['notAfter']}\n\n#{event['description']}",
45
+ :state => "ok",
46
+ :ttl => 300}
47
+
48
+ ev2 = if (event['code'] == 'instance-retirement') and
49
+ Date.today >= before-opts[:retirement_critical]
50
+ {:state => "critical"}
51
+ elsif opts[:event_warning] and Date.today >= before-opts[:event_warning]
52
+ {:state => "warning"}
53
+ else
54
+ {:state => "warning"}
55
+ end
56
+
57
+ report ev.merge(ev2)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ Riemann::Tools::AWS.run
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'riemann/tools'
4
+
5
+ $0 = __FILE__
6
+
7
+ class Riemann::Tools::ELBMetrics
8
+ include Riemann::Tools
9
+ require 'fog'
10
+ require 'time'
11
+
12
+ opt :fog_credentials_file, "Fog credentials file", :type => String
13
+ opt :fog_credential, "Fog credentials to use", :type => String
14
+ opt :aws_access, "AWS Access Key", :type => String
15
+ opt :aws_secret, "AWS Secret Key", :type => String
16
+ opt :aws_region, "AWS Region", :type => String, :default => "eu-west-1"
17
+ opt :aws_azs, "List of AZs to aggregate against", :type => :strings, :default => [ "all_az" ]
18
+ opt :elbs, "List of ELBs to pull metrics from", :type => :strings, :required => true
19
+
20
+ def standard_metrics
21
+ # ELB metric types, from:
22
+ # http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html#elb-metricscollected
23
+ metric_options = {
24
+ "Latency" => {
25
+ "Unit" => "Seconds",
26
+ "Statistics" => ["Maximum", "Minimum", "Average" ]
27
+ },
28
+ "RequestCount" => {
29
+ "Unit" => "Count",
30
+ "Statistics" => [ "Sum" ]
31
+ },
32
+ "HealthyHostCount" => {
33
+ "Units" => "Count",
34
+ "Statistics" => [ "Minimum", "Maximum", "Average" ]
35
+ },
36
+ "UnHealthyHostCount" => {
37
+ "Units" => "Count",
38
+ "Statistics" => [ "Minimum", "Maximum", "Average" ]
39
+ },
40
+ "HTTPCode_ELB_4XX" => {
41
+ "Units" => "Count",
42
+ "Statistics" => [ "Sum" ]
43
+ },
44
+ "HTTPCode_ELB_5XX" => {
45
+ "Units" => "Count",
46
+ "Statistics" => [ "Sum" ]
47
+ },
48
+ "HTTPCode_Backend_2XX" => {
49
+ "Units" => "Count",
50
+ "Statistics" => [ "Sum" ]
51
+ },
52
+ "HTTPCode_Backend_3XX" => {
53
+ "Units" => "Count",
54
+ "Statistics" => [ "Sum" ]
55
+ },
56
+ "HTTPCode_Backend_4XX" => {
57
+ "Units" => "Count",
58
+ "Statistics" => [ "Sum" ]
59
+ },
60
+ "HTTPCode_Backend_5XX" => {
61
+ "Units" => "Count",
62
+ "Statistics" => [ "Sum" ]
63
+ }
64
+ }
65
+
66
+ metric_options
67
+ end
68
+
69
+ def base_metrics
70
+ # get last 60 seconds
71
+ start_time = (Time.now.utc - 60).iso8601
72
+ end_time = Time.now.utc.iso8601
73
+
74
+ # The base query that all metrics would get
75
+ metric_base = {
76
+ "Namespace" => "AWS/ELB",
77
+ "StartTime" => start_time,
78
+ "EndTime" => end_time,
79
+ "Period" => 60,
80
+ }
81
+
82
+ metric_base
83
+ end
84
+
85
+
86
+ def tick
87
+ if options[:fog_credentials_file]
88
+ Fog.credentials_path = options[:fog_credentials_file]
89
+ Fog.credential = options[:fog_credential].to_sym
90
+ connection = Fog::AWS::CloudWatch.new
91
+ else
92
+ if options[:aws_access] && options[:aws_secret]
93
+ connection = Fog::AWS::CloudWatch.new({
94
+ :aws_access_key_id => options[:aws_access],
95
+ :aws_secret_access_key => options[:aws_secret],
96
+ :region => options[:aws_region]
97
+ })
98
+ else
99
+ connection = Fog::AWS::CloudWatch.new({
100
+ :use_iam_profile => true,
101
+ :region => options[:aws_region]
102
+ })
103
+ end
104
+ end
105
+
106
+ options[:elbs].each do |lb|
107
+
108
+ metric_options = standard_metrics
109
+ metric_base_options = base_metrics
110
+
111
+ options[:aws_azs].each do |az|
112
+ metric_options.keys.sort.each do |metric_type|
113
+ merged_options = metric_base_options.merge(metric_options[metric_type])
114
+ merged_options["MetricName"] = metric_type
115
+ if az == "all_az"
116
+ merged_options["Dimensions"] = [ { "Name" => "LoadBalancerName", "Value" => lb } ]
117
+ else
118
+ merged_options["Dimensions"] = [
119
+ { "Name" => "LoadBalancerName", "Value" => lb },
120
+ { "Name" => "AvailabilityZone" , "Value" => az}
121
+ ]
122
+ end
123
+
124
+ result = connection.get_metric_statistics(merged_options)
125
+
126
+ # "If no response codes in the category 2XX-5XX range are sent to clients within
127
+ # the given time period, values for these metrics will not be recorded in CloudWatch"
128
+ #next if result.body["GetMetricStatisticsResult"]["Datapoints"].empty? && metric_type =~ /[2345]XX/
129
+ #
130
+ # BUG:
131
+ # Metrics are reported every 60 seconds, but sometimes there isn't one there yet.
132
+ # We can skip that, or do something else?
133
+ next if result.body["GetMetricStatisticsResult"]["Datapoints"].empty?
134
+
135
+ # We should only ever have a single data point
136
+ result.body["GetMetricStatisticsResult"]["Datapoints"][0].keys.sort.each do |stat_type|
137
+ next if stat_type == "Unit"
138
+ next if stat_type == "Timestamp"
139
+
140
+ unit = result.body["GetMetricStatisticsResult"]["Datapoints"][0]["Unit"]
141
+ metric = result.body["GetMetricStatisticsResult"]["Datapoints"][0][stat_type]
142
+ event = Hash.new
143
+ event = {
144
+ host: lb,
145
+ service: "elb.#{az}.#{metric_type}.#{stat_type}",
146
+ ttl: 60,
147
+ description: "#{lb} #{metric_type} #{stat_type} (#{unit})",
148
+ tags: [ "production", "elb_metrics" ],
149
+ metric: metric
150
+ }
151
+
152
+ report(event)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ Riemann::Tools::ELBMetrics.run
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: riemann-aws
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kyle Kingsbury
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: riemann-tools
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: fog
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.4.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email: aphyr@aphyr.com
57
+ executables:
58
+ - riemann-aws-billing
59
+ - riemann-aws-rds-status
60
+ - riemann-aws-sqs-status
61
+ - riemann-aws-status
62
+ - riemann-elb-metrics
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - LICENSE
67
+ - README.md
68
+ - bin/riemann-aws-billing
69
+ - bin/riemann-aws-rds-status
70
+ - bin/riemann-aws-sqs-status
71
+ - bin/riemann-aws-status
72
+ - bin/riemann-elb-metrics
73
+ homepage: https://github.com/riemann/riemann-aws
74
+ licenses: []
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 1.8.7
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project: riemann-aws
92
+ rubygems_version: 2.4.5
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Submits aws stats to riemann.
96
+ test_files: []