Adapt dashboard to show idle and used runners

This commit is contained in:
Sebastian Serth
2021-12-06 23:56:31 +01:00
parent a4003ca733
commit 563e14a44a
8 changed files with 68 additions and 27 deletions

View File

@ -68,7 +68,7 @@ $(document).on('turbolinks:load', function() {
_.each(response.docker, function(data) { _.each(response.docker, function(data) {
groups.update({ groups.update({
id: data.id, id: data.id,
visible: data.pool_size > 0 visible: data.prewarmingPoolSize > 0
}); });
}); });
}; };
@ -78,26 +78,27 @@ $(document).on('turbolinks:load', function() {
dataset.add({ dataset.add({
group: data.id, group: data.id,
x: vis.moment(), x: vis.moment(),
y: data.quantity y: data.usedRunners
}); });
}); });
}; };
var updateProgressBar = function(progress_bar, data) { var updateProgressBar = function(progress_bar, data) {
var percentage = Math.min(Math.round(data.quantity / data.pool_size * 100), 100); var percentage = Math.min(Math.round(data.idleRunners / data.prewarmingPoolSize * 100), 100);
progress_bar.attr({ progress_bar.attr({
'aria-valuemax': data.pool_size, 'aria-valuemax': data.prewarmingPoolSize,
'aria-valuenow': data.quantity, 'aria-valuenow': data.idleRunners,
style: 'width: ' + percentage + '%' style: 'width: ' + percentage + '%'
}); });
progress_bar.html(data.quantity); progress_bar.html(data.idleRunners);
}; };
var updateTable = function(response) { var updateTable = function(response) {
_.each(response.docker, function(data) { _.each(response.docker, function(data) {
var row = $('tbody tr[data-id=' + data.id + ']'); var row = $('tbody tr[data-id=' + data.id + ']');
$('.pool-size', row).html(data.pool_size); $('.prewarming-pool-size', row).html(data.prewarmingPoolSize);
var progress_bar = $('.quantity .progress .progress-bar', row); $('.used-runners', row).html(`+ ${data.usedRunners}`);
var progress_bar = $('.idle-runners .progress .progress-bar', row);
updateProgressBar(progress_bar, data); updateProgressBar(progress_bar, data);
}); });
}; };

View File

@ -15,7 +15,18 @@ module Admin
end end
ExecutionEnvironment.order(:id).select(:id, :pool_size).map do |execution_environment| ExecutionEnvironment.order(:id).select(:id, :pool_size).map do |execution_environment|
execution_environment.attributes.merge(quantity: pool_size[execution_environment.id]) # Fetch the actual values (ID is stored as a symbol) or get an empty hash for merge
actual = pool_size[execution_environment.id.to_s.to_sym] || {}
template = {
id: execution_environment.id,
prewarmingPoolSize: execution_environment.pool_size,
idleRunners: 0,
usedRunners: 0,
}
# Existing values in the template get replaced with actual values
template.merge(actual)
end end
end end
end end

View File

@ -10,33 +10,38 @@ h1 = t('breadcrumbs.dashboard.show')
h2 Version h2 Version
div.mb-4 div.mb-4
= "CodeOcean Release:" = application_name
=< t("admin.dashboard.show.release")
| :
pre = Sentry.configuration.release pre = Sentry.configuration.release
- if Runner.management_active? - if Runner.management_active?
div.mb-4 div.mb-4
= Runner.strategy_class.name.demodulize = Runner.strategy_class.name.demodulize
=< "Release:" =< t("admin.dashboard.show.release")
| :
pre = Runner.strategy_class.release pre = Runner.strategy_class.release
h2 Docker h2 Docker
- if Runner.management_active? - if Runner.management_active?
h3 = t('.current') h3 = t('admin.dashboard.show.current')
.table-responsive .table-responsive
table.table table.table
thead thead
tr tr
th = t('activerecord.models.execution_environment.one') th = t('activerecord.models.execution_environment.one')
th = t('activerecord.attributes.execution_environment.pool_size') th = t('activerecord.attributes.execution_environment.pool_size')
th = t('.quantity') th = t('admin.dashboard.show.idleRunners')
th = t('admin.dashboard.show.usedRunners')
tbody tbody
- ExecutionEnvironment.order(:name).each do |execution_environment| - ExecutionEnvironment.order(:name).each do |execution_environment|
tr data-id=execution_environment.id tr data-id=execution_environment.id
td.name = link_to_if(policy(execution_environment).show?, execution_environment, execution_environment) td.name = link_to_if(policy(execution_environment).show?, execution_environment, execution_environment)
td.pool-size td.prewarming-pool-size
td.quantity = progress_bar(0) td.idle-runners = progress_bar(0)
h3 = t('.history') td.used-runners
h3 = t('admin.dashboard.show.history')
#graph #graph
- else - else
p = t('.inactive') p = t('admin.dashboard.show.inactive')

View File

@ -241,10 +241,12 @@ de:
admin: admin:
dashboard: dashboard:
show: show:
release: Release
current: Aktuelle Verfügbarkeit current: Aktuelle Verfügbarkeit
history: Verfügbarkeitsverlauf history: Nutzungsverlauf
inactive: Es ist kein Runner Management aktiv. inactive: Es ist kein Runner Management aktiv.
quantity: Verfügbare Container idleRunners: Freie Runner
usedRunners: Reservierte Runner
application: application:
not_authorized: Sie Sind nicht berechtigt, diese Aktion auszuführen. not_authorized: Sie Sind nicht berechtigt, diese Aktion auszuführen.
welcome: welcome:

View File

@ -241,10 +241,12 @@ en:
admin: admin:
dashboard: dashboard:
show: show:
release: Release
current: Current Availability current: Current Availability
history: Availability History history: Usage History
inactive: No runner management is currently enabled. inactive: No runner management is currently enabled.
quantity: Available Containers idleRunners: Idle Runners
usedRunners: Reserved Runners
application: application:
not_authorized: You are not authorized to perform this action. not_authorized: You are not authorized to perform this action.
welcome: welcome:

View File

@ -166,7 +166,7 @@ class Runner::Strategy::DockerContainerPool < Runner::Strategy
url = "#{config[:url]}/docker_container_pool/quantities" url = "#{config[:url]}/docker_container_pool/quantities"
response = Faraday.get(url) response = Faraday.get(url)
pool_size = JSON.parse(response.body) pool_size = JSON.parse(response.body)
pool_size.transform_keys(&:to_i) pool_size.deep_symbolize_keys
rescue Faraday::Error => e rescue Faraday::Error => e
raise Runner::Error::FaradayError.new("Request to DockerContainerPool failed: #{e.inspect}") raise Runner::Error::FaradayError.new("Request to DockerContainerPool failed: #{e.inspect}")
rescue JSON::ParserError => e rescue JSON::ParserError => e

View File

@ -176,7 +176,23 @@ class Runner::Strategy::Poseidon < Runner::Strategy
end end
def self.pool_size def self.pool_size
{} url = "#{config[:url]}/statistics/execution-environments"
Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Getting statistics from #{url}" }
response = http_connection.get url
case response.status
when 200
response_body = parse response
response_body
else
handle_error response
end
rescue Faraday::Error => e
raise Runner::Error::FaradayError.new("Request to Poseidon failed: #{e.inspect}")
rescue JSON::ParserError => e
# Poseidon should not send invalid json
raise Runner::Error::UnexpectedResponse.new("Error parsing response from Poseidon: #{e.message}")
ensure
Rails.logger.debug { "#{Time.zone.now.getutc.inspect}: Finished getting statistics" }
end end
def self.websocket_header def self.websocket_header

View File

@ -14,7 +14,7 @@ describe Admin::DashboardHelper do
FactoryBot.create(:ruby) FactoryBot.create(:ruby)
dcp = instance_double 'docker_container_pool' dcp = instance_double 'docker_container_pool'
allow(Runner).to receive(:strategy_class).and_return dcp allow(Runner).to receive(:strategy_class).and_return dcp
allow(dcp).to receive(:pool_size).and_return([]) allow(dcp).to receive(:pool_size).and_return({})
end end
it 'contains an entry for every execution environment' do it 'contains an entry for every execution environment' do
@ -22,11 +22,15 @@ describe Admin::DashboardHelper do
end end
it 'contains the pool size for every execution environment' do it 'contains the pool size for every execution environment' do
expect(docker_data.first.symbolize_keys).to include(:pool_size) expect(docker_data.first.symbolize_keys).to include(:prewarmingPoolSize)
end end
it 'contains the number of available containers for every execution environment' do it 'contains the number of idle runners for every execution environment' do
expect(docker_data.first).to include(:quantity) expect(docker_data.first).to include(:idleRunners)
end
it 'contains the number of used runners for every execution environment' do
expect(docker_data.first).to include(:usedRunners)
end end
end end
end end