heroku-vector 0.0.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
- data/.gitignore +37 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +95 -0
- data/README.md +171 -0
- data/Rakefile +10 -0
- data/bin/heroku_vector +91 -0
- data/config.rb.example +28 -0
- data/diagrams/Architecture.pptx +0 -0
- data/diagrams/Architecture/Slide1.png +0 -0
- data/examples/upstart_conf +10 -0
- data/heroku-vector.gemspec +38 -0
- data/lib/heroku_vector.rb +133 -0
- data/lib/heroku_vector/dyno_scaler.rb +133 -0
- data/lib/heroku_vector/engine/heroku.rb +63 -0
- data/lib/heroku_vector/helper.rb +23 -0
- data/lib/heroku_vector/process_manager.rb +61 -0
- data/lib/heroku_vector/sampler.rb +50 -0
- data/lib/heroku_vector/source/new_relic.rb +50 -0
- data/lib/heroku_vector/source/sidekiq.rb +49 -0
- data/lib/heroku_vector/version.rb +3 -0
- data/lib/heroku_vector/worker.rb +49 -0
- data/test/fixtures/vcr_cassettes/heroku_dyno_types.yml +69 -0
- data/test/fixtures/vcr_cassettes/heroku_scale_dynos.yml +65 -0
- data/test/fixtures/vcr_cassettes/newrelic_account.yml +78 -0
- data/test/fixtures/vcr_cassettes/newrelic_app.yml +134 -0
- data/test/fixtures/vcr_cassettes/newrelic_threshold_values.yml +192 -0
- data/test/heroku_vector/dyno_scaler_test.rb +240 -0
- data/test/heroku_vector/engine/heroku_test.rb +91 -0
- data/test/heroku_vector/sampler_test.rb +61 -0
- data/test/heroku_vector/source/new_relic_test.rb +77 -0
- data/test/heroku_vector/source/sidekiq_test.rb +78 -0
- data/test/test_helper.rb +40 -0
- metadata +313 -0
@@ -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,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
|