Refactor the SQL/query stuff into a dynamic class. Also merged all the config in a single hash.
This commit is contained in:
parent
954e18922e
commit
275292de47
4 changed files with 108 additions and 107 deletions
|
@ -13,11 +13,11 @@ module Gitlab
|
|||
|
||||
def issue_events
|
||||
# TODO figure out what the frontend needs for displaying the avatar
|
||||
@fetcher.fetch_issue_events.each { |event| parse_event(event) }
|
||||
@fetcher.fetch(stage: :issue).each { |event| parse_event(event) }
|
||||
end
|
||||
|
||||
def plan_events
|
||||
@fetcher.fetch_plan_events.each do |event|
|
||||
@fetcher.fetch(stage: :plan).each do |event|
|
||||
event['total_time'] = distance_of_time_in_words(event['total_time'].to_f)
|
||||
commits = event.delete('commits')
|
||||
event['commit'] = first_time_reference_commit(commits, event)
|
||||
|
@ -25,22 +25,22 @@ module Gitlab
|
|||
end
|
||||
|
||||
def code_events
|
||||
@fetcher.fetch_code_events.each { |event| parse_event(event) }
|
||||
@fetcher.fetch(stage: :code).each { |event| parse_event(event) }
|
||||
end
|
||||
|
||||
def test_events
|
||||
@fetcher.fetch_test_events.each do |event|
|
||||
@fetcher.fetch(stage: :test).each do |event|
|
||||
event['total_time'] = distance_of_time_in_words(event['total_time'].to_f)
|
||||
event['pipeline'] = ::Ci::Pipeline.find_by_id(event['ci_commit_id']) # we may not have a pipeline
|
||||
end
|
||||
end
|
||||
|
||||
def review_events
|
||||
@fetcher.fetch_review_events.each { |event| parse_event(event) }
|
||||
@fetcher.fetch(stage: :review).each { |event| parse_event(event) }
|
||||
end
|
||||
|
||||
def staging_events
|
||||
@fetcher.fetch_staging_events.each do |event|
|
||||
@fetcher.fetch(stage: :staging).each do |event|
|
||||
event['total_time'] = distance_of_time_in_words(event['total_time'].to_f)
|
||||
event['pipeline'] = ::Ci::Pipeline.find_by_id(event['ci_commit_id']) # we may not have a pipeline
|
||||
end
|
||||
|
|
|
@ -3,121 +3,73 @@ module Gitlab
|
|||
class EventsFetcher
|
||||
include MetricsFetcher
|
||||
|
||||
EVENTS_CONFIG = {
|
||||
issue: {
|
||||
start_time_attrs: issue_table[:created_at],
|
||||
end_time_attrs: [issue_metrics_table[:first_associated_with_milestone_at],
|
||||
issue_metrics_table[:first_added_to_board_at]],
|
||||
projections: [issue_table[:title], issue_table[:iid], issue_table[:created_at], user_table[:name]],
|
||||
project: @project,
|
||||
from: @from
|
||||
},
|
||||
plan: {
|
||||
start_time_attrs: issue_metrics_table[:first_associated_with_milestone_at],
|
||||
end_time_attrs: [issue_metrics_table[:first_added_to_board_at],
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]],
|
||||
projections: [mr_diff_table[:st_commits].as('commits'), issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
},
|
||||
code: {
|
||||
start_time_attrs: issue_metrics_table[:first_mentioned_in_commit_at],
|
||||
end_time_attrs: mr_table[:created_at],
|
||||
projections: [mr_table[:title], mr_table[:iid], mr_table[:created_at], user_table[:name]],
|
||||
order: mr_table[:created_at]
|
||||
},
|
||||
test: {
|
||||
start_time_attrs: mr_metrics_table[:latest_build_started_at],
|
||||
end_time_attrs: mr_metrics_table[:latest_build_finished_at],
|
||||
projections: mr_metrics_table[:ci_commit_id],
|
||||
order: mr_table[:created_at]
|
||||
},
|
||||
review: {
|
||||
start_time_attrs: mr_table[:created_at],
|
||||
end_time_attrs: mr_metrics_table[:merged_at],
|
||||
projections: [mr_table[:title], mr_table[:iid], mr_table[:created_at], user_table[:name]]
|
||||
},
|
||||
staging: {
|
||||
start_time_attrs: mr_metrics_table[:merged_at],
|
||||
end_time_attrs: mr_metrics_table[:first_deployed_to_production_at],
|
||||
projections: mr_metrics_table[:ci_commit_id]
|
||||
}
|
||||
}.freeze
|
||||
|
||||
def initialize(project:, from:)
|
||||
@project = project
|
||||
@from = from
|
||||
@query = EventsQuery.new(project: project, from: from)
|
||||
end
|
||||
|
||||
def fetch_issue_events
|
||||
base_query = base_query_for(:issue)
|
||||
diff_fn = subtract_datetimes_diff(base_query, issue_table[:created_at], issue_attributes)
|
||||
def fetch(stage:)
|
||||
custom_query = "#{stage}_custom_query".to_sym
|
||||
|
||||
query = base_query.join(user_table).on(issue_table[:author_id].eq(user_table[:id])).
|
||||
project(extract_epoch(diff_fn).as('total_time'), *issue_projections).
|
||||
order(issue_table[:created_at].desc)
|
||||
|
||||
execute(query)
|
||||
@query.execute(stage, EVENTS_CONFIG[stage]) do |base_query|
|
||||
public_send(custom_query, base_query) if self.respond_to?(custom_query)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_plan_events
|
||||
base_query = base_query_for(:plan)
|
||||
diff_fn = subtract_datetimes_diff(base_query,
|
||||
issue_metrics_table[:first_associated_with_milestone_at],
|
||||
plan_attributes)
|
||||
|
||||
query = base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id])).
|
||||
project(extract_epoch(diff_fn).as('total_time'), *plan_projections).
|
||||
order(issue_metrics_table[:first_associated_with_milestone_at].desc)
|
||||
|
||||
execute(query)
|
||||
def issue_custom_query(base_query)
|
||||
base_query.join(user_table).on(issue_table[:author_id].eq(user_table[:id]))
|
||||
end
|
||||
|
||||
def fetch_code_events
|
||||
base_query = base_query_for(:code)
|
||||
diff_fn = subtract_datetimes_diff(base_query,
|
||||
issue_metrics_table[:first_mentioned_in_commit_at],
|
||||
mr_table[:created_at])
|
||||
|
||||
query = base_query.join(user_table).on(issue_table[:author_id].eq(user_table[:id])).
|
||||
project(extract_epoch(diff_fn).as('total_time'), *code_projections).
|
||||
order(mr_table[:created_at].desc)
|
||||
|
||||
execute(query)
|
||||
def plan_custom_query(base_query)
|
||||
base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
|
||||
end
|
||||
|
||||
def fetch_test_events
|
||||
base_query = base_query_for(:test)
|
||||
diff_fn = subtract_datetimes_diff(base_query,
|
||||
mr_metrics_table[:latest_build_started_at],
|
||||
mr_metrics_table[:latest_build_finished_at])
|
||||
|
||||
query = base_query.project(extract_epoch(diff_fn).as('total_time'), mr_metrics_table[:ci_commit_id]).
|
||||
order(mr_table[:created_at].desc)
|
||||
|
||||
execute(query)
|
||||
def code_custom_query(base_query)
|
||||
base_query.join(user_table).on(issue_table[:author_id].eq(user_table[:id]))
|
||||
end
|
||||
|
||||
def fetch_review_events
|
||||
base_query = base_query_for(:review)
|
||||
diff_fn = subtract_datetimes_diff(base_query,
|
||||
mr_table[:created_at],
|
||||
mr_metrics_table[:merged_at])
|
||||
|
||||
query = base_query.join(user_table).on(mr_table[:author_id].eq(user_table[:id])).
|
||||
project(extract_epoch(diff_fn).as('total_time'), *code_projections).
|
||||
order(mr_table[:created_at].desc)
|
||||
|
||||
execute(query)
|
||||
end
|
||||
|
||||
def fetch_staging_events
|
||||
base_query = base_query_for(:staging)
|
||||
diff_fn = subtract_datetimes_diff(base_query,
|
||||
mr_metrics_table[:merged_at],
|
||||
mr_metrics_table[:first_deployed_to_production_at])
|
||||
|
||||
query = base_query.project(extract_epoch(diff_fn).as('total_time'), mr_metrics_table[:ci_commit_id]).
|
||||
order(mr_table[:created_at].desc)
|
||||
|
||||
execute(query)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def issue_attributes
|
||||
[issue_metrics_table[:first_associated_with_milestone_at],
|
||||
issue_metrics_table[:first_added_to_board_at]]
|
||||
end
|
||||
|
||||
def plan_attributes
|
||||
[issue_metrics_table[:first_added_to_board_at],
|
||||
issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
end
|
||||
|
||||
def issue_projections
|
||||
[issue_table[:title], issue_table[:iid], issue_table[:created_at], User.arel_table[:name]]
|
||||
end
|
||||
|
||||
def plan_projections
|
||||
[mr_diff_table[:st_commits].as('commits'), issue_metrics_table[:first_mentioned_in_commit_at]]
|
||||
end
|
||||
|
||||
def code_projections
|
||||
[mr_table[:title], mr_table[:iid], mr_table[:created_at], User.arel_table[:name]]
|
||||
end
|
||||
|
||||
def user_table
|
||||
User.arel_table
|
||||
end
|
||||
|
||||
def extract_epoch(arel_attribute)
|
||||
return arel_attribute unless Gitlab::Database.postgresql?
|
||||
|
||||
Arel.sql(%Q{EXTRACT(EPOCH FROM (#{arel_attribute.to_sql}))})
|
||||
end
|
||||
|
||||
def execute(query)
|
||||
ActiveRecord::Base.connection.execute(query.to_sql).to_a
|
||||
def review_custom_query(base_query)
|
||||
base_query.join(user_table).on(mr_table[:author_id].eq(user_table[:id]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
41
lib/gitlab/cycle_analytics/events_query.rb
Normal file
41
lib/gitlab/cycle_analytics/events_query.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
module Gitlab
|
||||
module CycleAnalytics
|
||||
class EventsQuery
|
||||
include MetricsFetcher
|
||||
|
||||
def initialize(project:, from:)
|
||||
@project = project
|
||||
@from = from
|
||||
end
|
||||
|
||||
def execute(stage, config, &block)
|
||||
@stage = stage
|
||||
@config = config
|
||||
query = build_query(&block)
|
||||
|
||||
ActiveRecord::Base.connection.execute(query.to_sql).to_a
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_query
|
||||
base_query = base_query_for(@stage)
|
||||
diff_fn = subtract_datetimes_diff(@config[:base_query], @config[:start_time_attrs], @config[:end_time_attrs])
|
||||
|
||||
yield base_query if block_given?
|
||||
|
||||
base_query.project(extract_epoch(diff_fn).as('total_time'), *@config[:projections]).order(order.desc)
|
||||
end
|
||||
|
||||
def order
|
||||
@config[:order] || @config[:start_time_attrs]
|
||||
end
|
||||
|
||||
def extract_epoch(arel_attribute)
|
||||
return arel_attribute unless Gitlab::Database.postgresql?
|
||||
|
||||
Arel.sql(%Q{EXTRACT(EPOCH FROM (#{arel_attribute.to_sql}))})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,6 +6,10 @@ module Gitlab
|
|||
|
||||
DEPLOYMENT_METRIC_STAGES = %i[production staging]
|
||||
|
||||
def self.included(klass)
|
||||
klass.extend self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def calculate_metric(name, start_time_attrs, end_time_attrs)
|
||||
|
@ -71,6 +75,10 @@ module Gitlab
|
|||
def issue_metrics_table
|
||||
Issue::Metrics.arel_table
|
||||
end
|
||||
|
||||
def user_table
|
||||
User.arel_table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue