cf_light_api 2.1.0 → 2.2.0.pre1

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 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