heroku-vector 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|