cf_light_api 2.1.0 → 2.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c695feed1d26f00127af6fac5fb24de9d64e0b56
4
- data.tar.gz: 42228f7a1efecd0f66f4f3ac0a1f31ad8de6d734
3
+ metadata.gz: 2285895d68ee80832326dad1a0e06ceb60630145
4
+ data.tar.gz: 6dafdfd47ebf9583f97eb8f8cfa0e2a1a5c8a891
5
5
  SHA512:
6
- metadata.gz: 6a412171a1799c8797bcd53e064cdad186154c42ab01d2bf46145b15f2d56ac9b3fbb6303f9140546478bbfc48e9bcba0d832b777b26ae280850acf15222772e
7
- data.tar.gz: 5de6fde920e3ad043ed7673a8fe0b70500665e377f076b1844a1f053b6c004180a95e87943a9c8f3fe028fedc525325e2ce51567db6f6463b5036ed4f57da00a
6
+ metadata.gz: 0d45598db25a9a7b54729a3b5caa0364b5c8cb21819549c1031f5ad042180fe0ae3e2211cda599f8cde9d9bfcc4fa22babfa56291d7d5f3c8cd1c04fe1e9a598
7
+ data.tar.gz: f1ba0ad880904e5c2bc36a2927468376ca6cd1c68169dd8ff09bc6e2aa10585ebd54b152fb807464353903de1335e9f647faa822bb0db307a90f9cb61479bcbe
data/bin/cf_light_api CHANGED
@@ -4,6 +4,16 @@ $stdout.sync = true
4
4
 
5
5
  puts '[cf_light_api] Starting CF Light API and worker...'
6
6
 
7
+ # If either of the minimum required New Relic settings are present, verify that they are both set, or exit with an error.
8
+ if ENV['NEW_RELIC_APP_NAME'] or ENV['NEW_RELIC_LICENSE_KEY']
9
+ ['NEW_RELIC_APP_NAME', 'NEW_RELIC_LICENSE_KEY'].each do |env|
10
+ unless ENV[env]
11
+ puts "[cf_light_api] Error: please set the '#{env}' environment variable to enable New Relic integration."
12
+ exit 1
13
+ end
14
+ end
15
+ end
16
+
7
17
  require_relative '../lib/cf_light_api/redis.rb'
8
18
  require_relative '../lib/cf_light_api/worker.rb'
9
19
 
@@ -6,154 +6,249 @@ require 'logger'
6
6
  require 'graphite-api'
7
7
  require 'date'
8
8
 
9
- require_relative 'lib.rb'
9
+ class CFLightAPIWorker
10
+ if ENV['NEW_RELIC_LICENSE_KEY']
11
+ require 'newrelic_rpm'
12
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
13
+ include NewRelic::Agent::MethodTracer
14
+ end
10
15
 
11
- @logger = Logger.new(STDOUT)
12
- @logger.formatter = proc do |severity, datetime, progname, msg|
13
- "#{datetime} [cf_light_api:worker]: #{msg}\n"
14
- end
16
+ def initialize
17
+ @logger = Logger.new(STDOUT)
18
+ @logger.formatter = proc do |severity, datetime, progname, msg|
19
+ "#{datetime} [cf_light_api:worker]: #{msg}\n"
20
+ end
21
+
22
+ ['CF_API', 'CF_USER', 'CF_PASSWORD'].each do |env|
23
+ unless ENV[env]
24
+ @logger.info "Error: please set the '#{env}' environment variable."
25
+ exit 1
26
+ end
27
+ end
28
+
29
+ # If either of the Graphite settings are set, verify that they are both set, or exit with an error.
30
+ if ENV['GRAPHITE_HOST'] or ENV['GRAPHITE_PORT']
31
+ ['GRAPHITE_HOST', 'GRAPHITE_PORT'].each do |env|
32
+ unless ENV[env]
33
+ @logger.info "Error: please set the '#{env}' environment variable to enable exporting to Graphite."
34
+ exit 1
35
+ end
36
+ end
37
+ end
38
+
39
+ update_interval = (ENV['UPDATE_INTERVAL'] || '5m').to_s # If you change the default '5m' here, also remember to change the default age validity in sinatra/cf_light_api.rb:31
40
+ update_timeout = (ENV['UPDATE_TIMEOUT'] || '5m').to_s
41
+
42
+ @lock_manager = Redlock::Client.new([ENV['REDIS_URI']])
43
+ @scheduler = Rufus::Scheduler.new
44
+
45
+ @logger.info "Update interval: '#{@update_interval}'"
46
+ @logger.info "Update timeout: '#{@update_timeout}'"
47
+
48
+ if ENV['GRAPHITE_HOST'] and ENV['GRAPHITE_PORT']
49
+ @logger.info "Graphite server: #{ENV['GRAPHITE_HOST']}:#{ENV['GRAPHITE_PORT']}"
50
+ else
51
+ @logger.info 'Graphite server: Disabled'
52
+ end
53
+
54
+ @scheduler.every update_interval, :first_in => '5s', :overlap => false, :timeout => update_timeout do
55
+ update_cf_data
56
+ end
15
57
 
16
- ['CF_API', 'CF_USER', 'CF_PASSWORD'].each do |env|
17
- unless ENV[env]
18
- @logger.info "Error: please set the '#{env}' environment variable."
19
- exit 1
20
58
  end
21
- end
22
59
 
23
- # If either of the Graphite settings are set, verify that they are both set, or exit with an error.
24
- if ENV['GRAPHITE_HOST'] or ENV['GRAPHITE_PORT']
25
- ['GRAPHITE_HOST', 'GRAPHITE_PORT'].each do |env|
26
- unless ENV[env]
27
- @logger.info "Error: please set the '#{env}' environment variable to enable exporting to Graphite."
28
- exit 1
60
+ def formatted_instance_stats_for_app app
61
+ instances = cf_rest("/v2/apps/#{app['metadata']['guid']}/stats")[0]
62
+ raise "Unable to retrieve app instance stats: '#{instances['error_code']}'" if instances['error_code']
63
+ instances.map{|key,value|value}
64
+ end
65
+
66
+ def cf_rest(path, method='GET')
67
+ @logger.info "Making #{method} request for #{path}..."
68
+
69
+ resources = []
70
+ response = JSON.parse(@cf_client.base.rest_client.request(method, path)[1][:body])
71
+
72
+ # Some endpoints return a 'resources' array, others are flat, depending on the path.
73
+ if response['resources']
74
+ resources << response['resources']
75
+ else
76
+ resources << response
29
77
  end
78
+
79
+ # Handle the pagination by recursing over myself until we get a response which doesn't contain a 'next_url'
80
+ # at which point all the resources are returned up the stack and flattened.
81
+ resources << cf_rest(response['next_url'], method) unless response['next_url'] == nil
82
+ resources.flatten
30
83
  end
31
- end
32
84
 
33
- UPDATE_INTERVAL = (ENV['UPDATE_INTERVAL'] || '5m').to_s # If you change the default '5m' here, also remember to change the default age validity in sinatra/cf_light_api.rb:31
34
- UPDATE_TIMEOUT = (ENV['UPDATE_TIMEOUT'] || '5m').to_s
85
+ def get_client(cf_api=ENV['CF_API'], cf_user=ENV['CF_USER'], cf_password=ENV['CF_PASSWORD'])
86
+ client = CFoundry::Client.get(cf_api)
87
+ client.login({:username => cf_user, :password => cf_password})
88
+ client
89
+ end
35
90
 
36
- lock_manager = Redlock::Client.new([ENV['REDIS_URI']])
37
- scheduler = Rufus::Scheduler.new
91
+ def send_instance_usage_data_to_graphite(instance_stats, org, space, app_name)
92
+ app_name.gsub! ".", "_" # Some apps have dots in the app name
38
93
 
39
- @logger.info "Update interval: '#{UPDATE_INTERVAL}'"
40
- @logger.info "Update timeout: '#{UPDATE_TIMEOUT}'"
94
+ instance_stats.each_with_index do |instance_data, index|
95
+ graphite_base_key = "cf_apps.#{org}.#{space}.#{app_name}.#{index}"
96
+ @logger.info " Exporting app instance \##{index} usage statistics to Graphite, path '#{graphite_base_key}'"
41
97
 
42
- if ENV['GRAPHITE_HOST'] and ENV['GRAPHITE_PORT']
43
- @logger.info "Graphite server: #{ENV['GRAPHITE_HOST']}:#{ENV['GRAPHITE_PORT']}"
44
- else
45
- @logger.info 'Graphite server: Disabled'
46
- end
98
+ # Quota data
99
+ ['mem_quota', 'disk_quota'].each do |key|
100
+ @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats'][key]
101
+ end
47
102
 
48
- scheduler.every UPDATE_INTERVAL, :first_in => '5s', :overlap => false, :timeout => UPDATE_TIMEOUT do
49
- @cf_client = nil
50
- @graphite = GraphiteAPI.new(graphite: "#{ENV['GRAPHITE_HOST']}:#{ENV['GRAPHITE_PORT']}") if ENV['GRAPHITE_HOST'] and ENV['GRAPHITE_PORT']
51
-
52
- begin
53
- lock_manager.lock("#{ENV['REDIS_KEY_PREFIX']}:lock", 5*60*1000) do |lock|
54
- if lock
55
- start_time = Time.now
56
-
57
- @logger.info "Updating data..."
58
-
59
- @cf_client = get_client() # Ensure we have a fresh auth token...
60
-
61
- @apps = cf_rest('/v2/apps?results-per-page=100')
62
- @orgs = cf_rest('/v2/organizations?results-per-page=100')
63
- @quotas = cf_rest('/v2/quota_definitions?results-per-page=100')
64
- @spaces = cf_rest('/v2/spaces?results-per-page=100')
65
- @stacks = cf_rest('/v2/stacks?results-per-page=100')
66
- @domains = cf_rest('/v2/domains?results-per-page=100')
67
-
68
- formatted_orgs = @orgs.map do |org|
69
- quota = @quotas.find{|a_quota| a_quota['metadata']['guid'] == org['entity']['quota_definition_guid']}
70
-
71
- {
72
- :guid => org['metadata']['guid'],
73
- :name => org['entity']['name'],
74
- :quota => {
75
- :name => quota['entity']['name'],
76
- :total_services => quota['entity']['total_services'],
77
- :total_routes => quota['entity']['total_routes'],
78
- :memory_limit => quota['entity']['memory_limit'] * 1024 * 1024
79
- }
80
- }
81
- end
103
+ # Usage data
104
+ ['mem', 'disk', 'cpu'].each do |key|
105
+ @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats']['usage'][key]
106
+ end
107
+ end
108
+ end
82
109
 
83
- formatted_apps = @apps.map do |app|
84
- # TODO: This is a bit repetative, could maybe improve?
85
- space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
86
- org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
87
- stack = @stacks.find{|a_stack| a_stack['metadata']['guid'] == app['entity']['stack_guid']}
88
- routes = format_routes_for_app(app)
89
-
90
- running = (app['entity']['state'] == "STARTED")
91
-
92
- base_data = {
93
- :buildpack => app['entity']['buildpack'],
94
- :data_from => Time.now.to_i,
95
- :diego => app['entity']['diego'],
96
- :docker => app['entity']['docker_image'] ? true : false,
97
- :docker_image => app['entity']['docker_image'],
98
- :guid => app['metadata']['guid'],
99
- :last_uploaded => app['metadata']['updated_at'] ? DateTime.parse(app['metadata']['updated_at']).strftime('%Y-%m-%d %T %z') : nil,
100
- :name => app['entity']['name'],
101
- :org => org['entity']['name'],
102
- :routes => routes,
103
- :space => space['entity']['name'],
104
- :stack => stack['entity']['name'],
105
- :state => app['entity']['state']
106
- }
107
-
108
- # Add additional data, such as instance usage statistics - but this is only possible if the instances are running.
109
- additional_data = {}
110
-
111
- begin
112
- instance_stats = []
113
- if running
114
- instance_stats = formatted_instance_stats_for_app(app)
115
- running_instances = instance_stats.select{|instance| instance['stats']['uris'] if instance['state'] == 'RUNNING'}
116
- raise "There are no running instances of this app." if running_instances.empty?
117
-
118
- if @graphite
119
- send_instance_usage_data_to_graphite(instance_stats, org['entity']['name'], space['entity']['name'], app['entity']['name'])
120
- end
121
- end
110
+ def put_in_redis(key, data)
111
+ REDIS.set key, data.to_json
112
+ end
122
113
 
123
- additional_data = {
124
- :running => running,
125
- :instances => instance_stats,
126
- :error => nil
127
- }
114
+ def format_duration(elapsed_seconds)
115
+ seconds = elapsed_seconds % 60
116
+ minutes = (elapsed_seconds / 60) % 60
117
+ hours = elapsed_seconds / (60 * 60)
118
+ format("%02d hrs, %02d mins, %02d secs", hours, minutes, seconds)
119
+ end
120
+
121
+ def format_routes_for_app app
122
+ routes = cf_rest app['entity']['routes_url']
123
+ routes.collect do |route|
124
+ host = route['entity']['host']
125
+ path = route['entity']['path']
126
+
127
+ domain = @domains.find{|a_domain| a_domain['metadata']['guid'] == route['entity']['domain_guid']}
128
+ domain = domain['entity']['name']
129
+
130
+ "#{host}.#{domain}#{path}"
131
+ end
132
+ end
128
133
 
129
- rescue => e
130
- # Most exceptions here will be caused by the app or one of the instances being in a non-standard state,
131
- # for example, trying to query an app which was present when the worker began updating, but was stopped
132
- # before we reached this section, so we just catch all exceptions, log the reason and move on.
133
- @logger.info " #{org['entity']['name']} #{space['entity']['name']}: '#{app['entity']['name']}' error: #{e.message}"
134
- additional_data = {
135
- :running => 'error',
136
- :instances => [],
137
- :error => e.message
134
+ def update_cf_data
135
+ @cf_client = nil
136
+ @graphite = GraphiteAPI.new(graphite: "#{ENV['GRAPHITE_HOST']}:#{ENV['GRAPHITE_PORT']}") if ENV['GRAPHITE_HOST'] and ENV['GRAPHITE_PORT']
137
+
138
+ begin
139
+ @lock_manager.lock("#{ENV['REDIS_KEY_PREFIX']}:lock", 5*60*1000) do |lock|
140
+ if lock
141
+ start_time = Time.now
142
+
143
+ @logger.info "Updating data..."
144
+
145
+ @cf_client = get_client() # Ensure we have a fresh auth token...
146
+
147
+ @apps = cf_rest('/v2/apps?results-per-page=100')
148
+ @orgs = cf_rest('/v2/organizations?results-per-page=100')
149
+ @quotas = cf_rest('/v2/quota_definitions?results-per-page=100')
150
+ @spaces = cf_rest('/v2/spaces?results-per-page=100')
151
+ @stacks = cf_rest('/v2/stacks?results-per-page=100')
152
+ @domains = cf_rest('/v2/domains?results-per-page=100')
153
+
154
+ formatted_orgs = @orgs.map do |org|
155
+ quota = @quotas.find{|a_quota| a_quota['metadata']['guid'] == org['entity']['quota_definition_guid']}
156
+
157
+ {
158
+ :guid => org['metadata']['guid'],
159
+ :name => org['entity']['name'],
160
+ :quota => {
161
+ :name => quota['entity']['name'],
162
+ :total_services => quota['entity']['total_services'],
163
+ :total_routes => quota['entity']['total_routes'],
164
+ :memory_limit => quota['entity']['memory_limit'] * 1024 * 1024
165
+ }
138
166
  }
139
167
  end
140
168
 
141
- base_data.merge additional_data
142
- end
169
+ formatted_apps = @apps.map do |app|
170
+ # TODO: This is a bit repetative, could maybe improve?
171
+ space = @spaces.find{|a_space| a_space['metadata']['guid'] == app['entity']['space_guid']}
172
+ org = @orgs.find{|an_org| an_org['metadata']['guid'] == space['entity']['organization_guid']}
173
+ stack = @stacks.find{|a_stack| a_stack['metadata']['guid'] == app['entity']['stack_guid']}
174
+ routes = format_routes_for_app(app)
175
+
176
+ running = (app['entity']['state'] == "STARTED")
177
+
178
+ base_data = {
179
+ :buildpack => app['entity']['buildpack'],
180
+ :data_from => Time.now.to_i,
181
+ :diego => app['entity']['diego'],
182
+ :docker => app['entity']['docker_image'] ? true : false,
183
+ :docker_image => app['entity']['docker_image'],
184
+ :guid => app['metadata']['guid'],
185
+ :last_uploaded => app['metadata']['updated_at'] ? DateTime.parse(app['metadata']['updated_at']).strftime('%Y-%m-%d %T %z') : nil,
186
+ :name => app['entity']['name'],
187
+ :org => org['entity']['name'],
188
+ :routes => routes,
189
+ :space => space['entity']['name'],
190
+ :stack => stack['entity']['name'],
191
+ :state => app['entity']['state']
192
+ }
193
+
194
+ # Add additional data, such as instance usage statistics - but this is only possible if the instances are running.
195
+ additional_data = {}
196
+
197
+ begin
198
+ instance_stats = []
199
+ if running
200
+ instance_stats = formatted_instance_stats_for_app(app)
201
+ running_instances = instance_stats.select{|instance| instance['stats']['uris'] if instance['state'] == 'RUNNING'}
202
+ raise "There are no running instances of this app." if running_instances.empty?
203
+
204
+ if @graphite
205
+ send_instance_usage_data_to_graphite(instance_stats, org['entity']['name'], space['entity']['name'], app['entity']['name'])
206
+ end
207
+ end
143
208
 
144
- put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:orgs", formatted_orgs
145
- put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps", formatted_apps
146
- put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:last_updated", {:last_updated => Time.now}
209
+ additional_data = {
210
+ :running => running,
211
+ :instances => instance_stats,
212
+ :error => nil
213
+ }
214
+
215
+ rescue => e
216
+ # Most exceptions here will be caused by the app or one of the instances being in a non-standard state,
217
+ # for example, trying to query an app which was present when the worker began updating, but was stopped
218
+ # before we reached this section, so we just catch all exceptions, log the reason and move on.
219
+ @logger.info " #{org['entity']['name']} #{space['entity']['name']}: '#{app['entity']['name']}' error: #{e.message}"
220
+ additional_data = {
221
+ :running => 'error',
222
+ :instances => [],
223
+ :error => e.message
224
+ }
225
+ end
226
+
227
+ base_data.merge additional_data
228
+ end
147
229
 
148
- @logger.info "Update completed in #{format_duration(Time.now.to_f - start_time.to_f)}..."
149
- lock_manager.unlock(lock)
150
- @cf_client.logout
151
- else
152
- @logger.info "Update already running in another instance!"
230
+ put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:orgs", formatted_orgs
231
+ put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:apps", formatted_apps
232
+ put_in_redis "#{ENV['REDIS_KEY_PREFIX']}:last_updated", {:last_updated => Time.now}
233
+
234
+ @logger.info "Update completed in #{format_duration(Time.now.to_f - start_time.to_f)}..."
235
+ @lock_manager.unlock(lock)
236
+ @cf_client.logout
237
+ else
238
+ @logger.info "Update already running in another instance!"
239
+ end
153
240
  end
241
+ rescue Rufus::Scheduler::TimeoutError
242
+ @logger.info 'Data update took too long and was aborted, waiting for the lock to expire before trying again...'
243
+ @cf_client.logout
154
244
  end
155
- rescue Rufus::Scheduler::TimeoutError
156
- @logger.info 'Data update took too long and was aborted, waiting for the lock to expire before trying again...'
157
- @cf_client.logout
158
245
  end
246
+
247
+ if ENV['NEW_RELIC_LICENSE_KEY']
248
+ add_transaction_tracer :update_cf_data, category: :task
249
+ add_method_tracer :update_cf_data
250
+ end
251
+
159
252
  end
253
+
254
+ CFLightAPIWorker.new
@@ -1,9 +1,15 @@
1
1
  require 'json'
2
2
 
3
+ if ENV['NEW_RELIC_LICENSE_KEY']
4
+ require 'newrelic_rpm'
5
+ NewRelic::Agent.manual_start
6
+ end
7
+
3
8
  module Sinatra
4
9
  module CfLightAPI
5
10
 
6
11
  def self.registered(app)
12
+
7
13
  app.get '/v1/apps/?:org?' do
8
14
  content_type :json
9
15
  all_apps = JSON.parse(REDIS.get("#{ENV['REDIS_KEY_PREFIX']}:apps"))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cf_light_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Springer Platform Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-09 00:00:00.000000000 Z
11
+ date: 2016-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cfoundry
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.1.6
97
+ - !ruby/object:Gem::Dependency
98
+ name: newrelic_rpm
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 3.17.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 3.17.1
97
111
  description: A super lightweight API for reading App and Org data from CloudFoundry,
98
112
  cached in Redis.
99
113
  email: ''
@@ -103,7 +117,6 @@ extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
105
119
  - ./lib/sinatra/cf_light_api.rb
106
- - ./lib/cf_light_api/lib.rb
107
120
  - ./lib/cf_light_api/redis.rb
108
121
  - ./lib/cf_light_api/worker.rb
109
122
  - bin/cf_light_api
@@ -122,9 +135,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
135
  version: '0'
123
136
  required_rubygems_version: !ruby/object:Gem::Requirement
124
137
  requirements:
125
- - - '>='
138
+ - - '>'
126
139
  - !ruby/object:Gem::Version
127
- version: '0'
140
+ version: 1.3.1
128
141
  requirements: []
129
142
  rubyforge_project:
130
143
  rubygems_version: 2.0.14
@@ -1,73 +0,0 @@
1
- def formatted_instance_stats_for_app app
2
- instances = cf_rest("/v2/apps/#{app['metadata']['guid']}/stats")[0]
3
- raise "Unable to retrieve app instance stats: '#{instances['error_code']}'" if instances['error_code']
4
- instances.map{|key,value|value}
5
- end
6
-
7
- def cf_rest(path, method='GET')
8
- @logger.info "Making #{method} request for #{path}..."
9
-
10
- resources = []
11
- response = JSON.parse(@cf_client.base.rest_client.request(method, path)[1][:body])
12
-
13
- # Some endpoints return a 'resources' array, others are flat, depending on the path.
14
- if response['resources']
15
- resources << response['resources']
16
- else
17
- resources << response
18
- end
19
-
20
- # Handle the pagination by recursing over myself until we get a response which doesn't contain a 'next_url'
21
- # at which point all the resources are returned up the stack and flattened.
22
- resources << cf_rest(response['next_url'], method) unless response['next_url'] == nil
23
- resources.flatten
24
- end
25
-
26
- def get_client(cf_api=ENV['CF_API'], cf_user=ENV['CF_USER'], cf_password=ENV['CF_PASSWORD'])
27
- client = CFoundry::Client.get(cf_api)
28
- client.login({:username => cf_user, :password => cf_password})
29
- client
30
- end
31
-
32
- def send_instance_usage_data_to_graphite(instance_stats, org, space, app_name)
33
- app_name.gsub! ".", "_" # Some apps have dots in the app name
34
-
35
- instance_stats.each_with_index do |instance_data, index|
36
- graphite_base_key = "cf_apps.#{org}.#{space}.#{app_name}.#{index}"
37
- @logger.info " Exporting app instance \##{index} usage statistics to Graphite, path '#{graphite_base_key}'"
38
-
39
- # Quota data
40
- ['mem_quota', 'disk_quota'].each do |key|
41
- @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats'][key]
42
- end
43
-
44
- # Usage data
45
- ['mem', 'disk', 'cpu'].each do |key|
46
- @graphite.metrics "#{graphite_base_key}.#{key}" => instance_data['stats']['usage'][key]
47
- end
48
- end
49
- end
50
-
51
- def put_in_redis(key, data)
52
- REDIS.set key, data.to_json
53
- end
54
-
55
- def format_duration(elapsed_seconds)
56
- seconds = elapsed_seconds % 60
57
- minutes = (elapsed_seconds / 60) % 60
58
- hours = elapsed_seconds / (60 * 60)
59
- format("%02d hrs, %02d mins, %02d secs", hours, minutes, seconds)
60
- end
61
-
62
- def format_routes_for_app app
63
- routes = cf_rest app['entity']['routes_url']
64
- routes.collect do |route|
65
- host = route['entity']['host']
66
- path = route['entity']['path']
67
-
68
- domain = @domains.find{|a_domain| a_domain['metadata']['guid'] == route['entity']['domain_guid']}
69
- domain = domain['entity']['name']
70
-
71
- "#{host}.#{domain}#{path}"
72
- end
73
- end