summaryrefslogtreecommitdiff
path: root/lib/gitlab/cycle_analytics
diff options
context:
space:
mode:
authorJames Lopez <james@jameslopez.es>2016-11-17 13:22:27 +0100
committerJames Lopez <james@jameslopez.es>2016-11-17 13:22:27 +0100
commited39d61d746925e49d952bd8169499d3200ae68b (patch)
tree33128144980f4b62e96309e9ed4c23133422159b /lib/gitlab/cycle_analytics
parentf9de157e70234748cf4285fafda7b3ec13862f5c (diff)
downloadgitlab-ce-ed39d61d746925e49d952bd8169499d3200ae68b.tar.gz
refactor events facade so it uses separate classes and refactor query stuff
Diffstat (limited to 'lib/gitlab/cycle_analytics')
-rw-r--r--lib/gitlab/cycle_analytics/base_config.rb17
-rw-r--r--lib/gitlab/cycle_analytics/base_event.rb27
-rw-r--r--lib/gitlab/cycle_analytics/code_event.rb (renamed from lib/gitlab/cycle_analytics/code_config.rb)9
-rw-r--r--lib/gitlab/cycle_analytics/event_config.rb (renamed from lib/gitlab/cycle_analytics/review_config.rb)2
-rw-r--r--lib/gitlab/cycle_analytics/events.rb54
-rw-r--r--lib/gitlab/cycle_analytics/events_fetcher.rb4
-rw-r--r--lib/gitlab/cycle_analytics/events_query.rb22
-rw-r--r--lib/gitlab/cycle_analytics/issue_event.rb (renamed from lib/gitlab/cycle_analytics/issue_config.rb)9
-rw-r--r--lib/gitlab/cycle_analytics/metrics_fetcher.rb42
-rw-r--r--lib/gitlab/cycle_analytics/metrics_tables.rb37
-rw-r--r--lib/gitlab/cycle_analytics/plan_config.rb17
-rw-r--r--lib/gitlab/cycle_analytics/plan_event.rb44
-rw-r--r--lib/gitlab/cycle_analytics/production_event.rb (renamed from lib/gitlab/cycle_analytics/production_config.rb)9
-rw-r--r--lib/gitlab/cycle_analytics/review_event.rb21
-rw-r--r--lib/gitlab/cycle_analytics/staging_event.rb (renamed from lib/gitlab/cycle_analytics/staging_config.rb)9
-rw-r--r--lib/gitlab/cycle_analytics/test_event.rb (renamed from lib/gitlab/cycle_analytics/test_config.rb)9
16 files changed, 196 insertions, 136 deletions
diff --git a/lib/gitlab/cycle_analytics/base_config.rb b/lib/gitlab/cycle_analytics/base_config.rb
deleted file mode 100644
index 06ae9a15a7a..00000000000
--- a/lib/gitlab/cycle_analytics/base_config.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Gitlab
- module CycleAnalytics
- class BaseConfig
- extend MetricsFetcher
-
- class << self
- attr_reader :start_time_attrs, :end_time_attrs, :projections
- end
-
- def self.order
- @order || @start_time_attrs
- end
-
- def self.query(base_query); end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/base_event.rb b/lib/gitlab/cycle_analytics/base_event.rb
new file mode 100644
index 00000000000..254e3621575
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/base_event.rb
@@ -0,0 +1,27 @@
+module Gitlab
+ module CycleAnalytics
+ class BaseEvent
+ extend MetricsTables
+
+ class << self
+ attr_reader :stage, :start_time_attrs, :end_time_attrs, :projections
+
+ def order
+ @order || @start_time_attrs
+ end
+
+ def query(base_query); end
+
+ def fetch(query)
+ query.execute(self).map { |event| serialize(event, query) }
+ end
+
+ private
+
+ def serialize(event, query)
+ raise NotImplementedError.new("Expected #{self.name} to implement serialize(event)")
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/code_config.rb b/lib/gitlab/cycle_analytics/code_event.rb
index c27419310db..609b45579b4 100644
--- a/lib/gitlab/cycle_analytics/code_config.rb
+++ b/lib/gitlab/cycle_analytics/code_event.rb
@@ -1,6 +1,7 @@
module Gitlab
module CycleAnalytics
- class CodeConfig < BaseConfig
+ class CodeEvent < BaseEvent
+ @stage = :code
@start_time_attrs = issue_metrics_table[:first_mentioned_in_commit_at]
@end_time_attrs = mr_table[:created_at]
@@ -13,6 +14,12 @@ module Gitlab
mr_table[:author_id]]
@order = mr_table[:created_at]
+
+ def self.serialize(event, query)
+ event['author'] = User.find(event.delete('author_id'))
+
+ AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/review_config.rb b/lib/gitlab/cycle_analytics/event_config.rb
index e91dc1ea104..2e1400c41b9 100644
--- a/lib/gitlab/cycle_analytics/review_config.rb
+++ b/lib/gitlab/cycle_analytics/event_config.rb
@@ -1,6 +1,6 @@
module Gitlab
module CycleAnalytics
- class ReviewConfig < BaseConfig
+ class TestEvent < BaseEvent
@start_time_attrs = mr_table[:created_at]
@end_time_attrs = mr_metrics_table[:merged_at]
diff --git a/lib/gitlab/cycle_analytics/events.rb b/lib/gitlab/cycle_analytics/events.rb
index 8e6e6b2f4a3..6580c73128c 100644
--- a/lib/gitlab/cycle_analytics/events.rb
+++ b/lib/gitlab/cycle_analytics/events.rb
@@ -3,73 +3,35 @@ module Gitlab
class Events
def initialize(project:, options:)
@project = project
- @fetcher = EventsFetcher.new(project: project, options: options)
+ @query = EventsQuery.new(project: project, options: options)
end
def issue_events
- @fetcher.fetch(stage: :issue).map { |event| serialize_event(event) }
+ IssueEvent.fetch(@query)
end
def plan_events
- @fetcher.fetch(stage: :plan).map do |event|
- st_commit = first_time_reference_commit(event.delete('commits'), event)
-
- next unless st_commit
-
- serialize_commit(event, st_commit)
- end
+ PlanEvent.fetch(@query)
end
def code_events
- @fetcher.fetch(stage: :code).map { |event| serialize_event(event, entity: :merge_request) }
+ CodeEvent.fetch(@query)
end
def test_events
- @fetcher.fetch(stage: :test).map { |event| serialize_build_event(event) }
+ TestEvent.fetch(@query)
end
def review_events
- @fetcher.fetch(stage: :review).map { |event| serialize_event(event, entity: :merge_request) }
+ ReviewEvent.fetch(@query)
end
def staging_events
- @fetcher.fetch(stage: :staging).map { |event| serialize_build_event(event) }
+ StagingEvent.fetch(@query)
end
def production_events
- @fetcher.fetch(stage: :production).map { |event| serialize_event(event) }
- end
-
- private
-
- def serialize_event(event, entity: :issue)
- event['author'] = User.find(event.delete('author_id'))
-
- AnalyticsGenericSerializer.new(project: @project, entity: entity).represent(event).as_json
- end
-
- def serialize_build_event(event)
- build = ::Ci::Build.find(event['id'])
-
- AnalyticsBuildSerializer.new.represent(build).as_json
- end
-
- def first_time_reference_commit(commits, event)
- YAML.load(commits).find do |commit|
- next unless commit[:committed_date] && event['first_mentioned_in_commit_at']
-
- commit[:committed_date].to_i == DateTime.parse(event['first_mentioned_in_commit_at'].to_s).to_i
- end
- end
-
- def serialize_commit(event, st_commit)
- commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
-
- AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit).as_json
- end
-
- def interval_in_words(diff)
- "#{distance_of_time_in_words(diff.to_f)} ago"
+ ProductionEvent.fetch(@query)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/events_fetcher.rb b/lib/gitlab/cycle_analytics/events_fetcher.rb
index 4c1d19774f5..813db46f058 100644
--- a/lib/gitlab/cycle_analytics/events_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/events_fetcher.rb
@@ -6,9 +6,7 @@ module Gitlab
end
def fetch(stage:)
- @query.execute(stage) do |stage_class, base_query|
- stage_class.query(base_query)
- end
+ @query.execute(stage)
end
end
end
diff --git a/lib/gitlab/cycle_analytics/events_query.rb b/lib/gitlab/cycle_analytics/events_query.rb
index b61320fc561..7ecdc07d17f 100644
--- a/lib/gitlab/cycle_analytics/events_query.rb
+++ b/lib/gitlab/cycle_analytics/events_query.rb
@@ -1,30 +1,30 @@
module Gitlab
module CycleAnalytics
class EventsQuery
- include MetricsFetcher
+ attr_reader :project
def initialize(project:, options: {})
@project = project
@from = options[:from]
@branch = options[:branch]
+ @fetcher = Gitlab::CycleAnalytics::MetricsFetcher.new(project: project, from: @from, branch: @branch)
end
- def execute(stage, &block)
- @stage = stage
- query = build_query(&block)
+ def execute(stage_class)
+ @stage_class = stage_class
ActiveRecord::Base.connection.exec_query(query.to_sql)
end
private
- def build_query
- base_query = base_query_for(@stage)
- diff_fn = subtract_datetimes_diff(base_query, stage_class.start_time_attrs, stage_class.end_time_attrs)
+ def query
+ base_query = @fetcher.base_query_for(@stage_class.stage)
+ diff_fn = @fetcher.subtract_datetimes_diff(base_query, @stage_class.start_time_attrs, @stage_class.end_time_attrs)
- yield(stage_class, base_query) if block_given?
+ @stage_class.query(base_query)
- base_query.project(extract_epoch(diff_fn).as('total_time'), *stage_class.projections).order(stage_class.order.desc)
+ base_query.project(extract_epoch(diff_fn).as('total_time'), *@stage_class.projections).order(@stage_class.order.desc)
end
def extract_epoch(arel_attribute)
@@ -32,10 +32,6 @@ module Gitlab
Arel.sql(%Q{EXTRACT(EPOCH FROM (#{arel_attribute.to_sql}))})
end
-
- def stage_class
- @stage_class ||= "Gitlab::CycleAnalytics::#{@stage.to_s.camelize}Config".constantize
- end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/issue_config.rb b/lib/gitlab/cycle_analytics/issue_event.rb
index 985ac76feb2..9cfcdc9b20e 100644
--- a/lib/gitlab/cycle_analytics/issue_config.rb
+++ b/lib/gitlab/cycle_analytics/issue_event.rb
@@ -1,6 +1,7 @@
module Gitlab
module CycleAnalytics
- class IssueConfig < BaseConfig
+ class IssueEvent < BaseEvent
+ @stage = :issue
@start_time_attrs = issue_table[:created_at]
@end_time_attrs = [issue_metrics_table[:first_associated_with_milestone_at],
@@ -11,6 +12,12 @@ module Gitlab
issue_table[:id],
issue_table[:created_at],
issue_table[:author_id]]
+
+ def self.serialize(event, query)
+ event['author'] = User.find(event.delete('author_id'))
+
+ AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/metrics_fetcher.rb b/lib/gitlab/cycle_analytics/metrics_fetcher.rb
index 6743cbcc9e0..b71e8735e27 100644
--- a/lib/gitlab/cycle_analytics/metrics_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/metrics_fetcher.rb
@@ -1,12 +1,18 @@
module Gitlab
module CycleAnalytics
- module MetricsFetcher
+ class MetricsFetcher
include Gitlab::Database::Median
include Gitlab::Database::DateTime
+ include MetricsTables
DEPLOYMENT_METRIC_STAGES = %i[production staging]
- private
+ def initialize(project:, from:, branch:)
+ @project = project
+ @project = project
+ @from = from
+ @branch = branch
+ end
def calculate_metric(name, start_time_attrs, end_time_attrs)
cte_table = Arel::Table.new("cte_table_for_#{name}")
@@ -49,38 +55,6 @@ module Gitlab
query
end
-
- def mr_metrics_table
- MergeRequest::Metrics.arel_table
- end
-
- def mr_table
- MergeRequest.arel_table
- end
-
- def mr_diff_table
- MergeRequestDiff.arel_table
- end
-
- def mr_closing_issues_table
- MergeRequestsClosingIssues.arel_table
- end
-
- def issue_table
- Issue.arel_table
- end
-
- def issue_metrics_table
- Issue::Metrics.arel_table
- end
-
- def user_table
- User.arel_table
- end
-
- def build_table
- ::CommitStatus.arel_table
- end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/metrics_tables.rb b/lib/gitlab/cycle_analytics/metrics_tables.rb
new file mode 100644
index 00000000000..9d25ef078e8
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/metrics_tables.rb
@@ -0,0 +1,37 @@
+module Gitlab
+ module CycleAnalytics
+ module MetricsTables
+ def mr_metrics_table
+ MergeRequest::Metrics.arel_table
+ end
+
+ def mr_table
+ MergeRequest.arel_table
+ end
+
+ def mr_diff_table
+ MergeRequestDiff.arel_table
+ end
+
+ def mr_closing_issues_table
+ MergeRequestsClosingIssues.arel_table
+ end
+
+ def issue_table
+ Issue.arel_table
+ end
+
+ def issue_metrics_table
+ Issue::Metrics.arel_table
+ end
+
+ def user_table
+ User.arel_table
+ end
+
+ def build_table
+ ::CommitStatus.arel_table
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/plan_config.rb b/lib/gitlab/cycle_analytics/plan_config.rb
deleted file mode 100644
index 453ee26b4c9..00000000000
--- a/lib/gitlab/cycle_analytics/plan_config.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Gitlab
- module CycleAnalytics
- class PlanConfig < BaseConfig
- @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]]
-
- def self.query(base_query)
- base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
- end
- end
- end
-end
diff --git a/lib/gitlab/cycle_analytics/plan_event.rb b/lib/gitlab/cycle_analytics/plan_event.rb
new file mode 100644
index 00000000000..b8107b06228
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/plan_event.rb
@@ -0,0 +1,44 @@
+module Gitlab
+ module CycleAnalytics
+ class PlanEvent < BaseEvent
+ @stage = :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]]
+
+ class << self
+ def query(base_query)
+ base_query.join(mr_diff_table).on(mr_diff_table[:merge_request_id].eq(mr_table[:id]))
+ end
+
+ private
+
+ def serialize(event, query)
+ st_commit = first_time_reference_commit(event.delete('commits'), event)
+
+ return unless st_commit
+
+ serialize_commit(event, st_commit, query)
+ end
+
+ def first_time_reference_commit(commits, event)
+ YAML.load(commits).find do |commit|
+ next unless commit[:committed_date] && event['first_mentioned_in_commit_at']
+
+ commit[:committed_date].to_i == DateTime.parse(event['first_mentioned_in_commit_at'].to_s).to_i
+ end
+ end
+
+ def serialize_commit(event, st_commit, query)
+ commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project)
+
+ AnalyticsCommitSerializer.new(project: query.project, total_time: event['total_time']).represent(commit).as_json
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/gitlab/cycle_analytics/production_config.rb b/lib/gitlab/cycle_analytics/production_event.rb
index dc9f1d5d059..b0b2d94f7e7 100644
--- a/lib/gitlab/cycle_analytics/production_config.rb
+++ b/lib/gitlab/cycle_analytics/production_event.rb
@@ -1,6 +1,7 @@
module Gitlab
module CycleAnalytics
- class ProductionConfig < BaseConfig
+ class ProductionEvent < BaseEvent
+ @stage = :production
@start_time_attrs = issue_table[:created_at]
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
@@ -10,6 +11,12 @@ module Gitlab
issue_table[:id],
issue_table[:created_at],
issue_table[:author_id]]
+
+ def self.serialize(event, query)
+ event['author'] = User.find(event.delete('author_id'))
+
+ AnalyticsIssueSerializer.new(project: query.project).represent(event).as_json
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/review_event.rb b/lib/gitlab/cycle_analytics/review_event.rb
new file mode 100644
index 00000000000..dcd138eaa92
--- /dev/null
+++ b/lib/gitlab/cycle_analytics/review_event.rb
@@ -0,0 +1,21 @@
+module Gitlab
+ module CycleAnalytics
+ class ReviewEvent < BaseEvent
+ @stage = :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[:id],
+ mr_table[:created_at],
+ mr_table[:state],
+ mr_table[:author_id]]
+
+ def self.serialize(event, _query)
+ event['author'] = User.find(event.delete('author_id'))
+
+ AnalyticsMergeRequestSerializer.new(project: query.project).represent(event).as_json
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cycle_analytics/staging_config.rb b/lib/gitlab/cycle_analytics/staging_event.rb
index f6f471286a0..a8872b50cfd 100644
--- a/lib/gitlab/cycle_analytics/staging_config.rb
+++ b/lib/gitlab/cycle_analytics/staging_event.rb
@@ -1,6 +1,7 @@
module Gitlab
module CycleAnalytics
- class StagingConfig < BaseConfig
+ class StagingEvent < BaseEvent
+ @stage = :staging
@start_time_attrs = mr_metrics_table[:merged_at]
@end_time_attrs = mr_metrics_table[:first_deployed_to_production_at]
@projections = [build_table[:id]]
@@ -9,6 +10,12 @@ module Gitlab
def self.query(base_query)
base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
end
+
+ def self.serialize(event, _query)
+ build = ::Ci::Build.find(event['id'])
+
+ AnalyticsBuildSerializer.new.represent(build).as_json
+ end
end
end
end
diff --git a/lib/gitlab/cycle_analytics/test_config.rb b/lib/gitlab/cycle_analytics/test_event.rb
index 6cb80f9a62c..c91d3f47da0 100644
--- a/lib/gitlab/cycle_analytics/test_config.rb
+++ b/lib/gitlab/cycle_analytics/test_event.rb
@@ -1,6 +1,7 @@
module Gitlab
module CycleAnalytics
- class TestConfig < BaseConfig
+ class TestEvent < BaseEvent
+ @stage = :test
@start_time_attrs = mr_metrics_table[:latest_build_started_at]
@end_time_attrs = mr_metrics_table[:latest_build_finished_at]
@projections = [build_table[:id]]
@@ -9,6 +10,12 @@ module Gitlab
def self.query(base_query)
base_query.join(build_table).on(mr_metrics_table[:pipeline_id].eq(build_table[:commit_id]))
end
+
+ def self.serialize(event, _query)
+ build = ::Ci::Build.find(event['id'])
+
+ AnalyticsBuildSerializer.new.represent(build).as_json
+ end
end
end
end