Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit 327bb97

Browse files
reidmitTeal Stannardmonamohebbi
committed
Add /v3/info/usage_summary endpoint
This endpoint allows admin-like users to see a rolled-up summary of usage across the whole platform. It calculates the number of started process instances and the total memory usage of started process instances and running tasks. [finishes #169070596] Co-authored-by: Reid Mitchell <rmitchell@pivotal.io> Co-authored-by: Teal Stannard <tstannard@pivotal.io> Co-authored-by: Mona Mohebbi <mmohebbi@pivotal.io>
1 parent 81059ef commit 327bb97

12 files changed

Lines changed: 212 additions & 6 deletions

File tree

app/controllers/v3/application_controller.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,19 @@ def service_unavailable!(message)
3737
def resource_not_found!(resource)
3838
raise CloudController::Errors::NotFound.new_from_details('ResourceNotFound', "#{resource.to_s.humanize} not found")
3939
end
40+
41+
def not_found!
42+
raise CloudController::Errors::NotFound.new_from_details('NotFound')
43+
end
4044
end
4145

4246
class ApplicationController < ActionController::Base
4347
include VCAP::CloudController
4448
include V3ErrorsHelper
4549
include VCAP::CloudController::ParamsHashifier
4650

47-
ANONYMOUSLY_AVAILABLE = ['not_found', 'internal_error', 'bad_request'].map(&:freeze).freeze
48-
UNSCOPED_PAGES = ['not_found', 'internal_error', 'bad_request', 'v3_root'].map(&:freeze).freeze
51+
ANONYMOUSLY_AVAILABLE = ['not_found', 'internal_error', 'bad_request', 'v3_info'].map(&:freeze).freeze
52+
UNSCOPED_PAGES = ['not_found', 'internal_error', 'bad_request', 'v3_root', 'v3_info'].map(&:freeze).freeze
4953
READ_SCOPE_HTTP_METHODS = ['GET', 'HEAD'].map(&:freeze).freeze
5054
YAML_CONTENT_TYPE = 'application/x-yaml'.freeze
5155

app/controllers/v3/info_controller.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
require 'fetchers/global_usage_summary_fetcher'
12
require 'presenters/v3/info_presenter'
3+
require 'presenters/v3/info_usage_summary_presenter'
24

3-
class InfoController < ActionController::Base
4-
def show
5+
class InfoController < ApplicationController
6+
def v3_info
57
info = Info.new
68
config = VCAP::CloudController::Config.config
79

@@ -16,6 +18,14 @@ def show
1618

1719
render status: :ok, json: VCAP::CloudController::Presenters::V3::InfoPresenter.new(info)
1820
end
21+
22+
def show_usage_summary
23+
not_found! unless permission_queryer.can_read_globally?
24+
25+
summary = VCAP::CloudController::GlobalUsageSummaryFetcher.summary
26+
27+
render status: :ok, json: VCAP::CloudController::Presenters::V3::InfoUsageSummaryPresenter.new(summary)
28+
end
1929
end
2030

2131
class Info
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module VCAP::CloudController
2+
class GlobalUsageSummaryFetcher
3+
class << self
4+
def summary
5+
summary = Summary.new
6+
7+
summary.started_instances = ProcessModel.
8+
dataset.
9+
where(state: ProcessModel::STARTED).
10+
sum(:instances) || 0
11+
12+
running_task_memory = TaskModel.
13+
dataset.
14+
where(state: TaskModel::RUNNING_STATE).
15+
sum(:memory_in_mb) || 0
16+
17+
started_app_memory = ProcessModel.
18+
dataset.
19+
where(state: ProcessModel::STARTED).
20+
sum(Sequel.*(:memory, :instances)) || 0
21+
22+
summary.memory_in_mb = running_task_memory + started_app_memory
23+
24+
summary
25+
end
26+
27+
class Summary
28+
attr_accessor :started_instances, :memory_in_mb
29+
end
30+
end
31+
end
32+
end
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require 'presenters/v3/base_presenter'
2+
require 'presenters/mixins/metadata_presentation_helpers'
3+
require 'presenters/helpers/censorship'
4+
5+
module VCAP::CloudController::Presenters::V3
6+
class InfoUsageSummaryPresenter < BasePresenter
7+
def to_hash
8+
{
9+
usage_summary: {
10+
started_instances: usage_summary.started_instances,
11+
memory_in_mb: usage_summary.memory_in_mb
12+
},
13+
links: {
14+
self: { href: build_self }
15+
}
16+
}
17+
end
18+
19+
private
20+
21+
def usage_summary
22+
@resource
23+
end
24+
25+
def build_self
26+
url_builder.build_url(path: '/v3/info/usage_summary')
27+
end
28+
end
29+
end

config/routes.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@
312312
delete '/roles/:guid', to: 'roles#destroy'
313313

314314
# info
315-
get '/info', to: 'info#show'
315+
get '/info', to: 'info#v3_info'
316+
get '/info/usage_summary', to: 'info#show_usage_summary'
316317

317318
namespace :internal do
318319
patch '/builds/:guid', to: 'builds#update'

docs/v3/source/includes/api_resources/_info.erb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,15 @@
3535
}
3636
}
3737
<% end %>
38+
39+
<% content_for :info_usage_summary do %>
40+
{
41+
"usage_summary": {
42+
"started_instances": 294,
43+
"memory_in_mb": 123945
44+
},
45+
"links": {
46+
"self": { "href": "http://api.example.com/v3/info/usage_summary" }
47+
}
48+
}
49+
<% end %>

docs/v3/source/includes/resources/info/_get.md.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ Content-Type: application/json
3232
```
3333

3434
#### Definition
35-
`GET /v3/info` <br>
35+
36+
`GET /v3/info`
3637

3738
#### Authentication
3839

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
### Get platform usage summary
2+
3+
```
4+
Example Request
5+
```
6+
7+
```shell
8+
curl "https://api.example.org/v3/info/usage_summary" \
9+
-X GET
10+
```
11+
12+
```
13+
Example Response
14+
```
15+
16+
```http
17+
HTTP/1.1 200 OK
18+
Content-Type: application/json
19+
20+
<%= yield_content :info_usage_summary %>
21+
```
22+
23+
This endpoint retrieves a high-level summary of usage across the entire Cloud Foundry installation.
24+
25+
#### Definition
26+
27+
`GET /v3/info/usage_summary`
28+
29+
#### Usage summary object
30+
31+
| Name | Type | Description |
32+
| ---- | ---- | ----------- |
33+
| **started_instances** | _integer_ | Total number of process instances in the `STARTED` state. |
34+
| **memory_in_mb** | _integer_ | Sum of memory usage of all tasks in the `RUNNING` state and all process instances in the `STARTED` state. |
35+
36+
#### Permitted roles
37+
38+
|
39+
--- | ---
40+
Admin |
41+
Admin Read-Only |
42+
Global Auditor |

docs/v3/source/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ includes:
142142
- resources/feature_flags/update
143143
- resources/info/header
144144
- resources/info/get
145+
- resources/info/get_usage_summary
145146
- resources/isolation_segments/header
146147
- resources/isolation_segments/object
147148
- resources/isolation_segments/create
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module VCAP::CloudController
2+
class GlobalUsageCalculator
3+
def self.instance_usage
4+
ProcessModel.dataset.where(state: ProcessModel::STARTED).sum(:instances) || 0
5+
end
6+
7+
def self.memory_usage
8+
0
9+
end
10+
end
11+
end

0 commit comments

Comments
 (0)