Merge pull request #108 from sschneid/api_summary_reorg

API summary rework
This commit is contained in:
Colin 2015-06-08 11:28:45 -07:00
commit b6cb20ba9f
3 changed files with 184 additions and 105 deletions

View file

@ -147,7 +147,9 @@ module Vmpooler
queue queue
end end
def get_tag_metrics(backend, date_str) def get_tag_metrics(backend, date_str, opts = {})
opts = {:only => false}.merge(opts)
tags = {} tags = {}
backend.hgetall('vmpooler__tag__' + date_str).each do |key, value| backend.hgetall('vmpooler__tag__' + date_str).each do |key, value|
@ -158,6 +160,10 @@ module Vmpooler
hostname, tag = key.split(':', 2) hostname, tag = key.split(':', 2)
end end
if opts[:only]
next unless tag == opts[:only]
end
tags[tag] ||= {} tags[tag] ||= {}
tags[tag][value] ||= 0 tags[tag][value] ||= 0
tags[tag][value] += 1 tags[tag][value] += 1
@ -169,8 +175,38 @@ module Vmpooler
tags tags
end end
def get_tag_summary(backend, from_date, to_date, opts = {})
opts = {:only => false}.merge(opts)
result = {
tag: {},
daily: []
}
(from_date..to_date).each do |date|
daily = {
date: date.to_s,
tag: get_tag_metrics(backend, date.to_s, opts)
}
result[:daily].push(daily)
end
result[:daily].each do |daily|
daily[:tag].each_key do |tag|
result[:tag][tag] ||= {}
daily[:tag][tag].each do |key, value|
result[:tag][tag][key] ||= 0
result[:tag][tag][key] += value
end
end
end
result
end
def get_task_metrics(backend, task_str, date_str, opts = {}) def get_task_metrics(backend, task_str, date_str, opts = {})
opts = {:bypool => false}.merge(opts) opts = {:bypool => false, :only => false}.merge(opts)
task = { task = {
duration: { duration: {
@ -226,9 +262,96 @@ module Vmpooler
task[:duration][:min], task[:duration][:max] = task_times.minmax task[:duration][:min], task[:duration][:max] = task_times.minmax
end end
if opts[:only]
task.each_key do |key|
task.delete(key) unless key.to_s == opts[:only]
end
end
task task
end end
def get_task_summary(backend, task_str, from_date, to_date, opts = {})
opts = {:bypool => false, :only => false}.merge(opts)
task_sym = task_str.to_sym
result = {
task_sym => {},
daily: []
}
(from_date..to_date).each do |date|
daily = {
date: date.to_s,
task_sym => get_task_metrics(backend, task_str, date.to_s, opts)
}
result[:daily].push(daily)
end
daily_task = {}
daily_task_bypool = {} if opts[:bypool] == true
result[:daily].each do |daily|
daily[task_sym].each_key do |type|
result[task_sym][type] ||= {}
daily_task[type] ||= {}
['min', 'max'].each do |key|
if daily[task_sym][type][key]
daily_task[type][:data] ||= []
daily_task[type][:data].push(daily[task_sym][type][key])
end
end
result[task_sym][type][:total] ||= 0
result[task_sym][type][:total] += daily[task_sym][type][:total]
if opts[:bypool] == true
result[task_sym][type][:pool] ||= {}
daily_task_bypool[type] ||= {}
next unless daily[task_sym][type][:pool]
daily[task_sym][type][:pool].each_key do |pool|
result[task_sym][type][:pool][pool] ||= {}
daily_task_bypool[type][pool] ||= {}
['min', 'max'].each do |key|
if daily[task_sym][type][:pool][pool][key.to_sym]
daily_task_bypool[type][pool][:data] ||= []
daily_task_bypool[type][pool][:data].push(daily[task_sym][type][:pool][pool][key.to_sym])
end
end
result[task_sym][type][:pool][pool][:total] ||= 0
result[task_sym][type][:pool][pool][:total] += daily[task_sym][type][:pool][pool][:total]
end
end
end
end
result[task_sym].each_key do |type|
if daily_task[type][:data]
result[task_sym][type][:min], result[task_sym][type][:max] = daily_task[type][:data].minmax
result[task_sym][type][:average] = mean(daily_task[type][:data])
end
if opts[:bypool] == true
result[task_sym].each_key do |type|
result[task_sym][type][:pool].each_key do |pool|
if daily_task_bypool[type][pool][:data]
result[task_sym][type][:pool][pool][:min], result[task_sym][type][:pool][pool][:max] = daily_task_bypool[type][pool][:data].minmax
result[task_sym][type][:pool][pool][:average] = mean(daily_task_bypool[type][pool][:data])
end
end
end
end
end
result
end
end end
end end
end end

View file

@ -11,6 +11,10 @@ module Vmpooler
call env.merge("PATH_INFO" => "/api/v#{api_version}/summary") call env.merge("PATH_INFO" => "/api/v#{api_version}/summary")
end end
get '/summary/:route/?:key?/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/summary/#{params[:route]}/#{params[:key]}")
end
post '/token/?' do post '/token/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/token") call env.merge("PATH_INFO" => "/api/v#{api_version}/token")
end end

View file

@ -67,39 +67,6 @@ module Vmpooler
content_type :json content_type :json
result = { result = {
boot: {
duration: {
average: 0,
min: 0,
max: 0,
total: 0,
pool: {}
},
count: {
average: 0,
min: 0,
max: 0,
total: 0,
pool: {}
}
},
clone: {
duration: {
average: 0,
min: 0,
max: 0,
total: 0,
pool: {}
},
count: {
average: 0,
min: 0,
max: 0,
total: 0,
pool: {}
}
},
tag: {},
daily: [] daily: []
} }
@ -121,90 +88,75 @@ module Vmpooler
halt 400, 'Date range is invalid, \'from\' must be in the past.' halt 400, 'Date range is invalid, \'from\' must be in the past.'
end end
(from_date..to_date).each do |date| boot = get_task_summary(backend, 'boot', from_date, to_date, :bypool => true)
daily = { clone = get_task_summary(backend, 'clone', from_date, to_date, :bypool => true)
date: date.to_s, tag = get_tag_summary(backend, from_date, to_date)
boot: get_task_metrics(backend, 'boot', date.to_s, :bypool => true),
clone: get_task_metrics(backend, 'clone', date.to_s, :bypool => true),
tag: get_tag_metrics(backend, date.to_s)
}
result[:daily].push(daily) result[:boot] = boot[:boot]
result[:clone] = clone[:clone]
result[:tag] = tag[:tag]
daily = {}
boot[:daily].each do |day|
daily[day[:date]] ||= {}
daily[day[:date]][:boot] = day[:boot]
end end
[:boot, :clone].each do |task| clone[:daily].each do |day|
daily_counts = [] daily[day[:date]] ||= {}
daily_counts_bypool = {} daily[day[:date]][:clone] = day[:clone]
daily_durations = [] end
daily_durations_bypool = {}
result[:daily].each do |daily| tag[:daily].each do |day|
if daily[task][:count][:pool] daily[day[:date]] ||= {}
daily[task][:count][:pool].each_key do |pool| daily[day[:date]][:tag] = day[:tag]
daily_counts_bypool[pool] ||= [] end
daily_counts_bypool[pool].push(daily[task][:count][:pool][pool][:total])
if daily[task][:count][:pool][pool][:total] > 0 daily.each_key do |day|
daily_durations_bypool[pool] ||= [] result[:daily].push({
daily_durations_bypool[pool].push(daily[task][:duration][:pool][pool][:min]) date: day,
daily_durations_bypool[pool].push(daily[task][:duration][:pool][pool][:max]) boot: daily[day][:boot],
end clone: daily[day][:clone],
tag: daily[day][:tag]
})
end
result[task][:count][:pool][pool] ||= {} JSON.pretty_generate(result)
result[task][:count][:pool][pool][:total] ||= 0 end
result[task][:count][:pool][pool][:total] += daily[task][:count][:pool][pool][:total]
result[task][:duration][:pool][pool] ||= {} get "#{api_prefix}/summary/:route/?:key?/?" do
result[task][:duration][:pool][pool][:total] ||= 0 content_type :json
result[task][:duration][:pool][pool][:total] += daily[task][:duration][:pool][pool][:total]
end
end
daily_counts.push(daily[task][:count][:total]) result = {}
if daily[task][:count][:total] > 0
daily_durations.push(daily[task][:duration][:min])
daily_durations.push(daily[task][:duration][:max])
end
result[task][:count][:total] += daily[task][:count][:total] from_param = params[:from] || Date.today.to_s
result[task][:duration][:total] += daily[task][:duration][:total] to_param = params[:to] || Date.today.to_s
end
if result[task][:count][:total] > 0 # Validate date formats
result[task][:duration][:average] = result[task][:duration][:total] / result[task][:count][:total] ##?? [from_param, to_param].each do |param|
end if !validate_date_str(param.to_s)
halt 400, "Invalid date format '#{param}', must match YYYY-MM-DD."
result[task][:count][:min], result[task][:count][:max] = daily_counts.minmax
result[task][:count][:average] = mean(daily_counts)
if daily_durations.length > 0
result[task][:duration][:min], result[task][:duration][:max] = daily_durations.minmax
end
daily_counts_bypool.each_key do |pool|
result[task][:count][:pool][pool][:min], result[task][:count][:pool][pool][:max] = daily_counts_bypool[pool].minmax
result[task][:count][:pool][pool][:average] = mean(daily_counts_bypool[pool])
if daily_durations_bypool[pool].length > 0
result[task][:duration][:pool][pool] ||= {}
result[task][:duration][:pool][pool][:min], result[task][:duration][:pool][pool][:max] = daily_durations_bypool[pool].minmax
end
if result[task][:count][:pool][pool][:total] > 0
result[task][:duration][:pool][pool][:average] = result[task][:duration][:pool][pool][:total] / result[task][:count][:pool][pool][:total]
end
end end
end end
result[:daily].each do |daily| from_date, to_date = Date.parse(from_param), Date.parse(to_param)
daily[:tag].each_key do |tag|
result[:tag][tag] ||= {}
daily[:tag][tag].each do |key, value| if to_date < from_date
result[:tag][tag][key] ||= 0 halt 400, 'Date range is invalid, \'to\' cannot come before \'from\'.'
result[:tag][tag][key] += value elsif from_date > Date.today
end halt 400, 'Date range is invalid, \'from\' must be in the past.'
end end
case params[:route]
when 'boot'
result = get_task_summary(backend, 'boot', from_date, to_date, :bypool => true, :only => params[:key])
when 'clone'
result = get_task_summary(backend, 'clone', from_date, to_date, :bypool => true, :only => params[:key])
when 'tag'
result = get_tag_summary(backend, from_date, to_date, :only => params[:key])
else
halt 404, JSON.pretty_generate({ 'ok' => false })
end end
JSON.pretty_generate(result) JSON.pretty_generate(result)