app/models/foreman_tasks/task/summarizer.rb in foreman-tasks-0.15.1 vs app/models/foreman_tasks/task/summarizer.rb in foreman-tasks-0.15.2

- old
+ new

@@ -1,15 +1,105 @@ module ForemanTasks class Task::Summarizer - def summarize_by_status(since = nil) - result = ::ForemanTasks::Task.where("result <> 'success'") - .select('count(state) AS count, state, result, max(started_at) AS started_at') - .group(:state, :result).order(:state) - result = result.where('started_at > ?', since) if since - result + ENSURED_STATE_KEYS = %w[running paused stopped scheduled].freeze + ENSURED_RESULT_KEYS = %w[success error warning].freeze + + # number of recent/total tasks for specific classification (state/result) + class Record + def initialize + @data = { recent: 0, total: 0 } + end + + def to_h + @data.dup + end + + # updates `field` (one of [:recent, :total]) with counts from aggregated_scope + def update(field, counts) + raise ArgumentError, "Unexpected field #{field}" unless @data.key?(field) + @data[field] = counts.sum(&:count) + end end + # number of recent/total tasks for specific state + distribution across different results + # in `by_result` attribute + class RecordWithResult < Record + attr_reader :by_result + + def initialize + super + @by_result = Hash.new { |h, k| h[k] = Record.new } + ENSURED_RESULT_KEYS.each { |result_value| @by_result[result_value] = Record.new } + end + + def to_h + by_result_hash = @by_result.each.with_object({}) do |(result, record), hash| + hash[result] = record.to_h + end + super.update(by_result: by_result_hash) + end + + # Updates the `field` summary + grouping by result + def update(field, counts) + super(field, counts) + counts.group_by(&:result).each do |(result, result_counts)| + @by_result[result].update(field, result_counts) + end + end + end + + def initialize(recent_timeframe = 24) + @recent_timeframe = recent_timeframe.hours + end + + def summarize_by_status + aggregated_scope.where("result <> 'success'") + end + def latest_tasks_in_errors_warning(limit = 5) ::ForemanTasks::Task.where('result in (?)', %w[error warning]).order('started_at DESC').limit(limit) + end + + # Returns summary of tasks count, grouped by `state` and `result`, if form of: + # + # { 'running' => { recent: 3, total: 6 }, + # 'paused' => { recent: 1, total: 3 }, + # 'stopped' => { recent: 3, total: 7, + # by_result: { + # 'success' => { recent: 2, total: 4 }, + # 'warning' => { recent: 1, total: 2 }, + # 'error' => { recent: 0, total: 1 }, + # }} + # 'scheduled' => { recent: 0, total: 3 }} + # + def summary + @summary = Hash.new { |h, state| h[state] = Record.new } + ENSURED_STATE_KEYS.each do |state| + @summary[state] = state == 'stopped' ? RecordWithResult.new : Record.new + end + + add_to_summary(aggregated_scope, :total) + add_to_summary(aggregated_recent_scope, :recent) + + @summary.each.with_object({}) do |(key, record), hash| + hash[key] = record.to_h + end + end + + private + + def add_to_summary(aggregated_scope, field) + aggregated_scope.group_by(&:state).each do |(state, state_counts)| + @summary[state].update(field, state_counts) + end + end + + def aggregated_scope + ::ForemanTasks::Task.select('count(state) AS count, state, result, max(started_at) AS started_at') + .group(:state, :result).order(:state) + end + + def aggregated_recent_scope + aggregated_scope.where("state_updated_at > ?", Time.now.utc - @recent_timeframe) end end end