cloudwatchtographite 0.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p448
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,25 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Required gems
4
+ gem 'bundler'
5
+ gem 'unf'
6
+ gem "fog", "~> 1.19.0"
7
+ gem 'hashifiable', '>= 0.1.3'
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem 'rdoc'
13
+ gem 'rspec'
14
+ gem 'rspec-mocks'
15
+ gem 'jeweler'
16
+ gem 'cane'
17
+ gem "factory_girl"
18
+ end
19
+
20
+ group :test do
21
+ gem 'rspec'
22
+ gem 'rspec-mocks'
23
+ gem "factory_girl"
24
+ gem 'coveralls', require: false
25
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 S. Zachariah Sprackett
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.
data/README.md ADDED
@@ -0,0 +1,138 @@
1
+ AWS CloudwatchToGraphite Ruby Gem
2
+ =================================
3
+
4
+ This application will fetch a list of AWS CloudWatch metrics using the Fog
5
+ library to connect to the Amazon APIs. It can parse a list of metric
6
+ definitions in either JSON or YAML formats. It will take the results and
7
+ submit them to a Graphite server of your choosing.
8
+
9
+ - [Fog](https://github.com/fog/fog)
10
+ - [Graphite](http://graphite.wikidot.com/)
11
+ - [AWS CloudWatch](http://aws.amazon.com/cloudwatch/)
12
+
13
+ [![Build Status](https://travis-ci.org/zsprackett/cloudwatchtographite.png?branch=master)](https://travis-ci.org/zsprackett/cloudwatchtographite)
14
+ [![Code Climate](https://codeclimate.com/github/zsprackett/cloudwatchtographite.png)](https://codeclimate.com/github/zsprackett/cloudwatchtographite)
15
+ [![Coverage Status](https://coveralls.io/repos/zsprackett/cloudwatchtographite/badge.png)](https://coveralls.io/r/zsprackett/cloudwatchtographite)
16
+ [![Dependency Status](https://gemnasium.com/zsprackett/cloudwatchtographite.png)](https://gemnasium.com/zsprackett/cloudwatchtographite)
17
+
18
+
19
+ Usage
20
+ -----
21
+
22
+ Usage: cloudwatch_to_graphite [OPTIONS]
23
+
24
+ -a, --access-key=KEY AWS Access Key (Falls back to ENV['AWS_ACCESS_KEY_ID'])
25
+ -s, --secret-key=KEY AWS Secret Access Key (Falls back to ENV['AWS_SECRET_ACCESS_KEY'])
26
+ -j, --json-metrics=FILE Path to JSON metrics file
27
+ -y, --yaml-metrics=FILE Path to YAML metrics file
28
+ -p, --protocol=udp TCP or UDP (Default: udp)
29
+ -r, --region=us-east-1 AWS Region (Default: us-east-1)
30
+ -g, --graphite-server=host Graphite Server (Default: localhost)
31
+ -P, --graphite-port=port Graphite Port (Default: 2003)
32
+ -c, --carbon-prefix Carbon Prefix (Default: cloudwatch)
33
+ -v, --verbose Increase verbosity
34
+ -V, --version Print version and exit
35
+ -h, --help help
36
+
37
+ JSON Metrics Definition File
38
+ ----------------------------
39
+
40
+ {
41
+ "metrics": [
42
+ {
43
+ "namespace": "AWS/ELB",
44
+ "metricname": "RequestCount",
45
+ "statistics": [ "Average", "Minimum", "Maximum" ],
46
+ "dimensions": [{
47
+ "name":"LoadBalancerName",
48
+ "value":"MyLoadBalancer"
49
+ }]
50
+ },
51
+ {
52
+ "namespace": "AWS/EC2",
53
+ "metricname": "CPUUtilization",
54
+ "statistics": [ "Average", "Minimum", "Maximum" ],
55
+ "dimensions": [{
56
+ "name":"InstanceId",
57
+ "value":"i-abc123456"
58
+ }]
59
+ }
60
+ ]
61
+ }
62
+
63
+ YAML Metrics Definition File
64
+ ----------------------------
65
+
66
+ ---
67
+ metrics:
68
+ -
69
+ namespace: AWS/ELB
70
+ metricname: RequestCount
71
+ statistics:
72
+ - Average
73
+ - Minimum
74
+ - Maximum
75
+ dimensions:
76
+ -
77
+ name: LoadBalancerName
78
+ value: MyLoadBalancer
79
+ -
80
+ namespace: AWS/EC2
81
+ metricname: CPUUtilization
82
+ statistics:
83
+ - Average
84
+ - Minimum
85
+ - Maximum
86
+ dimensions:
87
+ -
88
+ name: InstanceId
89
+ value: i-abc123456
90
+
91
+ Contributing
92
+ ------------
93
+
94
+ * Find something you would like to work on.
95
+ * Look for anything you can help with in the [issue tracker](https://github.com/zsprackett/cloudwatchtographite/issues).
96
+ * Look at the [code quality metrics](https://codeclimate.com/github/zsprackett/cloudwatchtographite) for anything you can help clean up.
97
+ * Look at the [test coverage](https://coveralls.io/r/zsprackett/cloudwatchtographite) for code in need of rspec tests.
98
+ * Do something else cool!
99
+ * Fork the project and do your work in a topic branch.
100
+ * Make sure your changes will work on both Ruby 1.9.3 and Ruby 2.0
101
+ * Add tests to prove your code works and run all the tests using `bundle exec rake`.
102
+ * Rebase your branch against `zsprackett/cloudwatchtographite` to make sure everything is up to date.
103
+ * Commit your changes and send a pull request.
104
+
105
+ Author
106
+ ------
107
+
108
+ [S. Zachariah Sprackett](mailto:zac@sprackett.com)
109
+
110
+ Copyright
111
+ ---------
112
+
113
+ (The MIT License)
114
+
115
+ Copyright (c) 2013 [zsprackett (S. Zachariah Sprackett)](http://github.com/zsprackett)
116
+
117
+ Permission is hereby granted, free of charge, to any person obtaining
118
+ a copy of this software and associated documentation files (the
119
+ "Software"), to deal in the Software without restriction, including
120
+ without limitation the rights to use, copy, modify, merge, publish,
121
+ distribute, sublicense, and/or sell copies of the Software, and to
122
+ permit persons to whom the Software is furnished to do so, subject to
123
+ the following conditions:
124
+
125
+ The above copyright notice and this permission notice shall be
126
+ included in all copies or substantial portions of the Software.
127
+
128
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
129
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
130
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
131
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
132
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
133
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
134
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
135
+
136
+
137
+ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/zsprackett/cloudwatchtographite/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
138
+
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ require './lib/cloudwatchtographite/version.rb'
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "cloudwatchtographite"
19
+ gem.homepage = "http://github.com/zsprackett/cloudwatchtographite"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{CloudWatch Metrics to Graphite}
22
+ gem.description = %Q{Pull statistics from Amazon CloudWatch into Graphite}
23
+ gem.email = "zac@sprackett.com"
24
+ gem.authors = ["S. Zachariah Sprackett"]
25
+ gem.version = CloudwatchToGraphite::VERSION::STRING
26
+ gem.executables = ["cloudwatch_to_graphite"]
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rspec/core'
31
+ require 'rspec/core/rake_task'
32
+ RSpec::Core::RakeTask.new(:spec) do |spec|
33
+ spec.pattern = FileList['spec/**/*_spec.rb']
34
+ end
35
+
36
+ require 'cane/rake_task'
37
+ Cane::RakeTask.new(:quality) do |cane|
38
+ cane.abc_max = 10
39
+ cane.add_threshold 'coverage/.last_run.json', :>=, 70
40
+ end
41
+
42
+ task :test => [:spec, :quality]
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ require './lib/cloudwatchtographite/version.rb'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = CloudwatchToGraphite::VERSION::STRING
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "CloudwatchToGraphite #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ # _*_ coding: utf-8 _*_
3
+ #
4
+ # == Synopsis
5
+ # CloudwatchToGraphite retrieves metrics from the Amazon CloudWatch APIs
6
+ # and passes them on to a graphite server
7
+ #
8
+ # == Author
9
+ # S. Zachariah Sprackett <zac@sprackett.com>
10
+ #
11
+ # == License
12
+ # The MIT License (MIT)
13
+ #
14
+ # == Copyright
15
+ # Copyright (C) 2013 - S. Zachariah Sprackett <zac@sprackett.com>
16
+ #
17
+
18
+ require 'optparse'
19
+ require 'pp'
20
+
21
+ begin
22
+ require 'cloudwatchtographite'
23
+ rescue LoadError
24
+ dev_path = File.join(File.dirname(__FILE__), '..', 'lib')
25
+ $:.unshift(dev_path)
26
+ require 'cloudwatchtographite'
27
+ end
28
+
29
+
30
+ # default options
31
+ options = {
32
+ :protocol => 'udp',
33
+ :region => ENV.has_key?('AWS_DEFAULT_REGION') ?
34
+ ENV['AWS_DEFAULT_REGION'] : 'us-east-1',
35
+ :access_key => ENV['AWS_ACCESS_KEY_ID'],
36
+ :secret_key => ENV['AWS_SECRET_ACCESS_KEY'],
37
+ :graphite_server => 'localhost',
38
+ :graphite_port => 2003,
39
+ :carbon_prefix => 'cloudwatch',
40
+ :verbose => false
41
+ }
42
+ opt_parser = OptionParser.new do |opt|
43
+ opt.banner = "Usage: %s [OPTIONS]" % File.basename($0)
44
+ opt.separator ""
45
+ opt.on("-a","--access-key=KEY","AWS Access Key (Falls back to ENV['AWS_ACCESS_KEY_ID'])") do |key|
46
+ options[:access_key] = key
47
+ end
48
+ opt.on("-s","--secret-key=KEY","AWS Secret Access Key (Falls back to ENV['AWS_SECRET_ACCESS_KEY'])") do |key|
49
+ options[:secret_key] = key
50
+ end
51
+ opt.on("-j","--json-metrics=FILE","Path to JSON metrics file") do |file|
52
+ options[:json_metrics] = file
53
+ end
54
+ opt.on("-y","--yaml-metrics=FILE","Path to YAML metrics file") do |file|
55
+ options[:yaml_metrics] = file
56
+ end
57
+ opt.on("-p","--protocol=udp","TCP or UDP (Default: #{options[:protocol]})") do |protocol|
58
+ options[:protocol] = protocol
59
+ end
60
+ opt.on("-r","--region=us-east-1","AWS Region (Default: #{options[:region]})") do |region|
61
+ options[:region] = region
62
+ end
63
+ opt.on("-g","--graphite-server=host","Graphite Server (Default: #{options[:graphite_server]})") do |server|
64
+ options[:graphite_server] = server
65
+ end
66
+ opt.on("-P","--graphite-port=port", Integer, "Graphite Port (Default: #{options[:graphite_port]})") do |port|
67
+ options[:graphite_port] = port
68
+ end
69
+ opt.on("-c","--carbon-prefix=prefix","Carbon Prefix (Default: #{options[:carbon_prefix]})") do |prefix|
70
+ options[:carbon_prefix] = prefix
71
+ end
72
+ opt.on("-v","--verbose","Increase verbosity") do
73
+ options[:verbose] = true
74
+ end
75
+ opt.on("-V","--version","Print version and exit") do
76
+ puts File.basename($0) + " " + CloudwatchToGraphite::VERSION::STRING
77
+ exit 0
78
+ end
79
+ opt.on("-h","--help","help") do
80
+ puts opt_parser
81
+ exit 1
82
+ end
83
+ end
84
+ begin
85
+ opt_parser.parse!
86
+ mandatory = [ :access_key, :secret_key ]
87
+ missing = mandatory.select{ |param| options[param].nil? }
88
+ if not missing.empty?
89
+ puts "Missing options: #{missing.join(', ')}"
90
+ puts opt_parser
91
+ exit 1
92
+ end
93
+ if options[:json_metrics].nil? and options[:yaml_metrics].nil?
94
+ puts "No metric file specified."
95
+ puts opt_parser
96
+ exit 1
97
+ elsif not options[:json_metrics].nil? and not options[:yaml_metrics].nil?
98
+ puts "Only one metric file should be specified."
99
+ puts opt_parser
100
+ exit 1
101
+ end
102
+ rescue OptionParser::InvalidOption => e
103
+ puts "Error: #{e}"
104
+ puts
105
+ puts opt_parser
106
+ exit 1
107
+ end
108
+
109
+ metrics = nil
110
+ begin
111
+ if not options[:json_metrics].nil?
112
+ metrics = CloudwatchToGraphite::LoadMetrics.from_json_file(options[:json_metrics])
113
+ else
114
+ metrics = CloudwatchToGraphite::LoadMetrics.from_yaml_file(options[:yaml_metrics])
115
+ end
116
+ rescue CloudwatchToGraphite::ParseError
117
+ warn "Failed to parse option file"
118
+ exit 1
119
+ end
120
+
121
+ if metrics.empty?
122
+ warn "Exiting due to lack of metric definitions"
123
+ exit 1
124
+ end
125
+
126
+ cwtg = CloudwatchToGraphite::Base.new(
127
+ options[:access_key],
128
+ options[:secret_key],
129
+ options[:region],
130
+ options[:verbose]
131
+ )
132
+
133
+ cwtg.carbon_prefix = options[:carbon_prefix]
134
+ cwtg.protocol = options[:protocol]
135
+ cwtg.graphite_server = options[:graphite_server]
136
+ cwtg.graphite_port = options[:graphite_port]
137
+
138
+ if cwtg.fetch_and_forward(metrics)
139
+ exit 0
140
+ else
141
+ exit 1
142
+ end
@@ -0,0 +1,23 @@
1
+ {
2
+ "metrics": [
3
+ {
4
+ "namespace": "AWS/ELB",
5
+ "metricname": "RequestCount",
6
+ "statistics": [ "Average", "Minimum", "Maximum" ],
7
+ "unit": "Count/Second",
8
+ "dimensions": [{
9
+ "name":"LoadBalancerName",
10
+ "value":"MyLoadBalancer"
11
+ }]
12
+ },
13
+ {
14
+ "namespace": "AWS/EC2",
15
+ "metricname": "CPUUtilization",
16
+ "statistics": [ "Average", "Minimum", "Maximum" ],
17
+ "dimensions": [{
18
+ "name":"InstanceId",
19
+ "value":"i-abc123456"
20
+ }]
21
+ }
22
+ ]
23
+ }
@@ -0,0 +1,25 @@
1
+ ---
2
+ metrics:
3
+ -
4
+ namespace: AWS/ELB
5
+ metricname: RequestCount
6
+ statistics:
7
+ - Average
8
+ - Minimum
9
+ - Maximum
10
+ unit: Count/Second
11
+ dimensions:
12
+ -
13
+ name: LoadBalancerName
14
+ value: MyLoadBalancer
15
+ -
16
+ namespace: AWS/EC2
17
+ metricname: CPUUtilization
18
+ statistics:
19
+ - Average
20
+ - Minimum
21
+ - Maximum
22
+ dimensions:
23
+ -
24
+ name: InstanceId
25
+ value: i-abc123456
@@ -0,0 +1,36 @@
1
+ # _*_ coding: utf-8 _*_
2
+ # == Synopsis
3
+ # CloudwatchToGraphite retrieves metrics from the Amazon CloudWatch APIs
4
+ # and passes them on to a graphite server
5
+ #
6
+ # == Author
7
+ # S. Zachariah Sprackett <zac@sprackett.com>
8
+ #
9
+ # == License
10
+ # The MIT License (MIT)
11
+ #
12
+ # == Copyright
13
+ # Copyright (C) 2013 - S. Zachariah Sprackett <zac@sprackett.com>
14
+ #
15
+ module CloudwatchToGraphite
16
+ # general exception class. ancestor to all CloudwatchToGraphite exceptions
17
+ class Exception < ::RuntimeError; end
18
+
19
+ # Raised when the arguments are wrong
20
+ class ArgumentError < Exception; end
21
+
22
+ # Raised when an argument is too long
23
+ class ArgumentLengthError < ArgumentError; end
24
+
25
+ # Raised when an argument is of the wrong type
26
+ class ArgumentTypeError < ArgumentError; end
27
+
28
+ # Raised when too many dimensions are specified
29
+ class TooManyDimensionError < Exception; end
30
+
31
+ # Raised when parsing fails
32
+ class ParseError < Exception; end
33
+
34
+ # Raised when an unknown protocol is used to try to send to graphite
35
+ class ProtocolError < Exception; end
36
+ end
@@ -0,0 +1,70 @@
1
+ # _*_ coding: utf-8 _*_
2
+ # == Synopsis
3
+ # CloudwatchToGraphite retrieves metrics from the Amazon CloudWatch APIs
4
+ # and passes them on to a graphite server
5
+ #
6
+ # == Author
7
+ # S. Zachariah Sprackett <zac@sprackett.com>
8
+ #
9
+ # == License
10
+ # The MIT License (MIT)
11
+ #
12
+ # == Copyright
13
+ # Copyright (C) 2013 - S. Zachariah Sprackett <zac@sprackett.com>
14
+ #
15
+ require 'json'
16
+ require 'yaml'
17
+
18
+ module CloudwatchToGraphite
19
+ # Load metrics from a file and parse them into a
20
+ # CloudwatchToGraphite::MetricDefinition object
21
+ #
22
+ class LoadMetrics
23
+ def self.from_json_file(filename)
24
+ if not File.readable?(filename)
25
+ warn "Unable to read %s" % filename
26
+ []
27
+ else
28
+ File.open(filename, 'r') do |f|
29
+ begin
30
+ contents = JSON.load(f)
31
+ load_content(contents)
32
+ rescue Exception
33
+ warn "Failed to parse %s" % filename
34
+ []
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.from_yaml_file(filename)
41
+ if not File.readable?(filename)
42
+ warn "Unable to read %s" % filename
43
+ []
44
+ else
45
+ begin
46
+ contents = YAML.load_file(filename)
47
+ load_content(contents)
48
+ rescue Exception
49
+ warn "Failed to parse %s" % filename
50
+ []
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+ def self.load_content(contents, strict=false)
57
+ metrics = []
58
+ Validator::hash_with_key_of_type(contents,'metrics',Array)
59
+ contents['metrics'].each do |m|
60
+ parsed = MetricDefinition::create_and_fill m
61
+ if (parsed != false)
62
+ metrics.push(parsed)
63
+ else
64
+ warn "Failed to parse #{m}."
65
+ end
66
+ end
67
+ metrics
68
+ end
69
+ end
70
+ end