heroku-vector 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,50 @@
1
+
2
+ module HerokuVector
3
+ class Sampler
4
+ include HerokuVector::Helper
5
+
6
+ attr_reader :capacity, :data
7
+
8
+ def initialize(capacity)
9
+ @capacity = capacity
10
+ clear
11
+ end
12
+
13
+ def clear
14
+ @data = []
15
+ end
16
+
17
+ def full?
18
+ @capacity == size
19
+ end
20
+
21
+ def size
22
+ data.size
23
+ end
24
+
25
+ def push(value)
26
+ data.push value
27
+ data.shift if size > capacity
28
+ end
29
+ alias_method :<<, :push
30
+
31
+ def mean
32
+ return 0 unless size >= 1
33
+
34
+ mean_value = data.reduce(:+).to_f / size.to_f
35
+ round_to_one_decimal( mean_value )
36
+ end
37
+
38
+ class << self
39
+ def capacity_for_sample_period(period_in_sec)
40
+ case period_in_sec
41
+ when 60; 5 # Last 5 mins (every minute)
42
+ when 10; 2 * 6 # Last 2 mins
43
+ when 5; 2 * 12 # Last 2 mins (every 5s)
44
+ when 1; 2 * 60 # Last 2 mins (every sec)
45
+ else; 100
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ require 'newrelic_api'
2
+
3
+ module HerokuVector::Source
4
+ class NewRelic
5
+ attr_reader :account_id, :app_id, :api_key
6
+
7
+ def initialize(options={})
8
+ options[:api_key] ||= HerokuVector.newrelic_api_key
9
+ options[:account_id] ||= HerokuVector.newrelic_account_id
10
+ options[:app_id] ||= HerokuVector.newrelic_app_id
11
+
12
+ @api_key = options[:api_key]
13
+ @account_id = options[:account_id]
14
+ @app_id = options[:app_id]
15
+
16
+ NewRelicApi.api_key = api_key
17
+ end
18
+
19
+ def newrelic_account
20
+ # Safe to memoize the parent Account
21
+ @newrelic_account ||= NewRelicApi::Account.find(account_id || :first)
22
+ end
23
+
24
+ def newrelic_app
25
+ # App Must be fetched from network every time, to get latest metrics
26
+ if app_id
27
+ newrelic_account.applications.find {|app| app.id == app_id }
28
+ else
29
+ newrelic_account.applications.first
30
+ end
31
+ end
32
+
33
+ def throughput
34
+ begin
35
+ # Fetch fresh App instance and extract Trhoughput metric from Threshold Values
36
+ # Threshold Values are current instantaneous measures, not periodic averages
37
+ metric = newrelic_app.threshold_values.find {|m| m.name == 'Throughput' }
38
+ metric.metric_value
39
+ rescue
40
+ return 0.0
41
+ end
42
+ end
43
+ alias_method :sample, :throughput
44
+
45
+ def unit
46
+ 'RPM'
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ require 'redis'
2
+ require 'redis-namespace'
3
+ require 'sidekiq'
4
+ require 'sidekiq/api'
5
+
6
+ module HerokuVector::Source
7
+ class Sidekiq
8
+ def initialize(options={})
9
+ configure_sidekiq_client(options)
10
+ end
11
+
12
+ def configure_sidekiq_client(options={})
13
+ ::Sidekiq.configure_client do |config|
14
+ pool_options = { :size => 3, :timeout => 10 }
15
+ config.redis = ConnectionPool.new(pool_options) { build_redis_client(options) }
16
+ end
17
+ end
18
+
19
+ def build_redis_client(options={})
20
+ return options[:redis] if options[:redis]
21
+
22
+ connection = Redis.new({
23
+ url: options[:redis_url] || HerokuVector.sidekiq_redis_url,
24
+ timeout: 60
25
+ })
26
+
27
+ namespace = options[:redis_namespace] || HerokuVector.sidekiq_redis_namespace
28
+ if namespace
29
+ return ::Redis::Namespace.new(namespace, redis: connection)
30
+ else
31
+ return connection
32
+ end
33
+ end
34
+
35
+ def sidekiq_processes
36
+ ::Sidekiq::ProcessSet.new
37
+ end
38
+
39
+ def busy_workers
40
+ sidekiq_processes.reduce(0) {|i, process| i + process['busy'].to_i }
41
+ end
42
+ alias_method :sample, :busy_workers
43
+
44
+ def unit
45
+ 'busy threads'
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module HerokuVector
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,49 @@
1
+ require 'eventmachine'
2
+
3
+ module HerokuVector
4
+ class Worker
5
+ include HerokuVector::Helper
6
+
7
+ attr_accessor :options, :dyno_scalers, :engine
8
+
9
+ def initialize(options={})
10
+ @options = options
11
+ @dyno_scalers = []
12
+ end
13
+
14
+ def run
15
+ if options[:config]
16
+ if File.exist?(options[:config])
17
+ logger.info "Loading config from '#{options[:config]}'"
18
+ load options[:config]
19
+ else
20
+ logger.fatal "No config found at '#{options[:config]}'"
21
+ logger.info "You can copy config.rb.example => config.rb to get started"
22
+ logger.info "OR run heroku_vector -c /path/to/your/config.rb"
23
+ logger.info "Just Starting? Test your Source config with sampler mode: heroku_vector -s"
24
+ exit 1
25
+ end
26
+ end
27
+
28
+ load_dyno_scalers
29
+
30
+ EM.run do
31
+ dyno_scalers.each do |scaler|
32
+ EM::PeriodicTimer.new(scaler.period) do
33
+ scaler.run
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def load_dyno_scalers
40
+ HerokuVector.dyno_scalers.each do |scaler_def|
41
+ name, options = scaler_def
42
+ logger.info "Loading Scaler: #{name}, #{options.inspect}"
43
+
44
+ @dyno_scalers << DynoScaler.new(name, options)
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,69 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.heroku.com/apps/app_name/dyno-types
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip
14
+ User-Agent:
15
+ - heroku-rb/0.3.19
16
+ X-Ruby-Version:
17
+ - 2.1.2
18
+ X-Ruby-Platform:
19
+ - x86_64-darwin12.0
20
+ Authorization:
21
+ - Basic REAL_AUTH_GOES_HERE
22
+ response:
23
+ status:
24
+ code: 200
25
+ message: ''
26
+ headers:
27
+ Content-Encoding:
28
+ - gzip
29
+ Content-Type:
30
+ - application/json;charset=utf-8
31
+ Date:
32
+ - Sun, 07 Sep 2014 03:55:14 GMT
33
+ Etag:
34
+ - '"2066ae00e17dbce2b2a0a51ddcb99426"'
35
+ Last-Modified:
36
+ - Sun, 07 Sep 2014 03:54:22 GMT
37
+ Oauth-Scope:
38
+ - global
39
+ Oauth-Scope-Accepted:
40
+ - global read read-protected write write-protected
41
+ Request-Id:
42
+ - c2abc0bf-d7e4-4840-b2c6-742038b43334
43
+ Server:
44
+ - nginx/1.4.7
45
+ Status:
46
+ - 200 OK
47
+ Vary:
48
+ - Accept-Encoding
49
+ X-Content-Type-Options:
50
+ - nosniff
51
+ X-Ratelimit-Remaining:
52
+ - '2399'
53
+ X-Runtime:
54
+ - '0.050453792'
55
+ Content-Length:
56
+ - '207'
57
+ Connection:
58
+ - keep-alive
59
+ body:
60
+ encoding: ASCII-8BIT
61
+ string: !binary |-
62
+ H4sIAO7WC1QAA3yOPQ+CQAyG/0pzMx/iSOKmA3EyjsaYu6Niw9GDAwRj/O9C
63
+ ogEcnNq+yfs8PT2FtkUhORWxQL7DMdnu9slh07gWQbWcGgTsUUNNKeZUga8h
64
+ WoFfwY2y2zhTvMrWNONayhKdNlQKT7AscGB21uXohrtqJTfUPES8fnlzqyIO
65
+ OSPuL52T5QBYaJ0kVrarR28QastXysJvGDg1M6FaaKIfzQKa41T8XFNz9a9J
66
+ pobhjdqaGWIK5pTzGwAA//8DAJawUYVeAQAA
67
+ http_version:
68
+ recorded_at: Sun, 07 Sep 2014 03:55:13 GMT
69
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,65 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.heroku.com/apps/app_name/ps/scale?qty=1&type=web
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip
14
+ User-Agent:
15
+ - heroku-rb/0.3.19
16
+ X-Ruby-Version:
17
+ - 2.1.2
18
+ X-Ruby-Platform:
19
+ - x86_64-darwin12.0
20
+ Authorization:
21
+ - Basic YOUR_AUTH_HERE==
22
+ response:
23
+ status:
24
+ code: 200
25
+ message: ''
26
+ headers:
27
+ Content-Encoding:
28
+ - gzip
29
+ Content-Type:
30
+ - text/html;charset=utf-8
31
+ Date:
32
+ - Sun, 07 Sep 2014 04:24:14 GMT
33
+ Oauth-Scope:
34
+ - global
35
+ Oauth-Scope-Accepted:
36
+ - global write write-protected
37
+ Request-Id:
38
+ - 034d545b-b3e7-4f69-a0bb-89d57630f6e4
39
+ Server:
40
+ - nginx/1.4.7
41
+ Status:
42
+ - 200 OK
43
+ Vary:
44
+ - Accept-Encoding
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Frame-Options:
48
+ - SAMEORIGIN
49
+ X-Ratelimit-Remaining:
50
+ - '2399'
51
+ X-Runtime:
52
+ - '0.118657809'
53
+ X-Xss-Protection:
54
+ - 1; mode=block
55
+ Content-Length:
56
+ - '27'
57
+ Connection:
58
+ - keep-alive
59
+ body:
60
+ encoding: ASCII-8BIT
61
+ string: !binary |-
62
+ H4sIAO7dC1QAAzIEAAAA//8DALfv3IMBAAAA
63
+ http_version:
64
+ recorded_at: Sun, 07 Sep 2014 04:24:13 GMT
65
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,78 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://rpm.newrelic.com/accounts.xml
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/xml
12
+ X-Api-Key:
13
+ - api_key
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ User-Agent:
17
+ - Ruby
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - nginx
25
+ Date:
26
+ - Sun, 07 Sep 2014 06:28:44 GMT
27
+ Content-Type:
28
+ - application/xml; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ Status:
34
+ - 200 OK
35
+ X-Newrelic-Api-Version:
36
+ - v1
37
+ Etag:
38
+ - '"6421a9efd042eb1f557d443b6010b3b9"'
39
+ Cache-Control:
40
+ - max-age=0, private, must-revalidate
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ X-Runtime:
44
+ - '0.016534'
45
+ body:
46
+ encoding: UTF-8
47
+ string: |
48
+ <?xml version="1.0" encoding="UTF-8"?>
49
+ <accounts type="array">
50
+ <account>
51
+ <allow-rails-core>false</allow-rails-core>
52
+ <api-key>api_key</api-key>
53
+ <data-access-key>8fe689a3c6e5b099a28551733333c2acaeb2a80136c9357</data-access-key>
54
+ <id type="integer">231237</id>
55
+ <license-key>adb4b49abefe681dce6d228d764082f1b36c9357</license-key>
56
+ <name>polar-rails-staging Heroku</name>
57
+ <partner-external-identifier nil="true"></partner-external-identifier>
58
+ <phone-number nil="true"></phone-number>
59
+ <event-feed-uri>/account_feeds/8fe689a3c6e5b099a28551733333c2acaeb2a80136c9357/events.rss</event-feed-uri>
60
+ <primary-admin>
61
+ <email>cole.jeff.services@gmail.com</email>
62
+ <first-name nil="true"></first-name>
63
+ <last-name nil="true"></last-name>
64
+ <state>active</state>
65
+ </primary-admin>
66
+ <subscription>
67
+ <annual-renewal-on nil="true"></annual-renewal-on>
68
+ <expires-on nil="true"></expires-on>
69
+ <number-of-hosts>unlimited</number-of-hosts>
70
+ <starts-on>2013-11-02</starts-on>
71
+ <state>free</state>
72
+ <product-name>Standard</product-name>
73
+ </subscription>
74
+ </account>
75
+ </accounts>
76
+ http_version:
77
+ recorded_at: Sun, 07 Sep 2014 06:28:43 GMT
78
+ recorded_with: VCR 2.9.2
@@ -0,0 +1,134 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://rpm.newrelic.com/accounts.xml
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/xml
12
+ X-Api-Key:
13
+ - api_key
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ User-Agent:
17
+ - Ruby
18
+ response:
19
+ status:
20
+ code: 200
21
+ message: OK
22
+ headers:
23
+ Server:
24
+ - nginx
25
+ Date:
26
+ - Sun, 07 Sep 2014 06:32:38 GMT
27
+ Content-Type:
28
+ - application/xml; charset=utf-8
29
+ Transfer-Encoding:
30
+ - chunked
31
+ Connection:
32
+ - keep-alive
33
+ Status:
34
+ - 200 OK
35
+ X-Newrelic-Api-Version:
36
+ - v1
37
+ Etag:
38
+ - '"6421a9efd042eb1f557d443b6010b3b9"'
39
+ Cache-Control:
40
+ - max-age=0, private, must-revalidate
41
+ X-Ua-Compatible:
42
+ - IE=Edge,chrome=1
43
+ X-Runtime:
44
+ - '0.019620'
45
+ body:
46
+ encoding: UTF-8
47
+ string: |
48
+ <?xml version="1.0" encoding="UTF-8"?>
49
+ <accounts type="array">
50
+ <account>
51
+ <allow-rails-core>false</allow-rails-core>
52
+ <api-key>api_key</api-key>
53
+ <data-access-key>8fe689a3c6e5b099a28551733333c2acaeb2a80136c9357</data-access-key>
54
+ <id type="integer">1</id>
55
+ <license-key>adb4b49abefe681dce6d228d764082f1b36c9357</license-key>
56
+ <name>polar-rails-staging Heroku</name>
57
+ <partner-external-identifier nil="true"></partner-external-identifier>
58
+ <phone-number nil="true"></phone-number>
59
+ <event-feed-uri>/account_feeds/8fe689a3c6e5b099a28551733333c2acaeb2a80136c9357/events.rss</event-feed-uri>
60
+ <primary-admin>
61
+ <email>cole.jeff.services@gmail.com</email>
62
+ <first-name nil="true"></first-name>
63
+ <last-name nil="true"></last-name>
64
+ <state>active</state>
65
+ </primary-admin>
66
+ <subscription>
67
+ <annual-renewal-on nil="true"></annual-renewal-on>
68
+ <expires-on nil="true"></expires-on>
69
+ <number-of-hosts>unlimited</number-of-hosts>
70
+ <starts-on>2013-11-02</starts-on>
71
+ <state>free</state>
72
+ <product-name>Standard</product-name>
73
+ </subscription>
74
+ </account>
75
+ </accounts>
76
+ http_version:
77
+ recorded_at: Sun, 07 Sep 2014 06:32:37 GMT
78
+ - request:
79
+ method: get
80
+ uri: http://rpm.newrelic.com/accounts/1/applications.xml
81
+ body:
82
+ encoding: US-ASCII
83
+ string: ''
84
+ headers:
85
+ Accept:
86
+ - application/xml
87
+ X-Api-Key:
88
+ - api_key
89
+ Accept-Encoding:
90
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
91
+ User-Agent:
92
+ - Ruby
93
+ response:
94
+ status:
95
+ code: 200
96
+ message: OK
97
+ headers:
98
+ Server:
99
+ - nginx
100
+ Date:
101
+ - Sun, 07 Sep 2014 06:32:38 GMT
102
+ Content-Type:
103
+ - application/xml; charset=utf-8
104
+ Transfer-Encoding:
105
+ - chunked
106
+ Connection:
107
+ - keep-alive
108
+ Status:
109
+ - 200 OK
110
+ X-Newrelic-Api-Version:
111
+ - v1
112
+ Etag:
113
+ - '"a2f87f24fee08dc231c1275662707617"'
114
+ Cache-Control:
115
+ - max-age=0, private, must-revalidate
116
+ X-Ua-Compatible:
117
+ - IE=Edge,chrome=1
118
+ X-Runtime:
119
+ - '0.026049'
120
+ body:
121
+ encoding: UTF-8
122
+ string: |
123
+ <?xml version="1.0" encoding="UTF-8"?>
124
+ <applications type="array">
125
+ <application>
126
+ <id type="integer">app_id</id>
127
+ <name>polar-rails-staging</name>
128
+ <overview-url>https://rpm.newrelic.com/accounts/1/applications/app_id</overview-url>
129
+ <servers-url>https://rpm.newrelic.com/api/v1/accounts/1/applications/app_id/servers</servers-url>
130
+ </application>
131
+ </applications>
132
+ http_version:
133
+ recorded_at: Sun, 07 Sep 2014 06:32:37 GMT
134
+ recorded_with: VCR 2.9.2