Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
b8056669
Commit
b8056669
authored
Dec 01, 2016
by
James Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor cycle analytics - updated based on MR feedback
parent
8183e848
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
107 additions
and
85 deletions
+107
-85
app/controllers/projects/cycle_analytics/events_controller.rb
...controllers/projects/cycle_analytics/events_controller.rb
+8
-8
app/controllers/projects/cycle_analytics_controller.rb
app/controllers/projects/cycle_analytics_controller.rb
+2
-2
app/models/cycle_analytics.rb
app/models/cycle_analytics.rb
+4
-8
app/serializers/analytics_stage_entity.rb
app/serializers/analytics_stage_entity.rb
+1
-3
lib/gitlab/cycle_analytics/base_event.rb
lib/gitlab/cycle_analytics/base_event.rb
+7
-3
lib/gitlab/cycle_analytics/base_stage.rb
lib/gitlab/cycle_analytics/base_stage.rb
+13
-6
lib/gitlab/cycle_analytics/class_name_util.rb
lib/gitlab/cycle_analytics/class_name_util.rb
+13
-0
lib/gitlab/cycle_analytics/code_stage.rb
lib/gitlab/cycle_analytics/code_stage.rb
+5
-7
lib/gitlab/cycle_analytics/event.rb
lib/gitlab/cycle_analytics/event.rb
+9
-0
lib/gitlab/cycle_analytics/issue_stage.rb
lib/gitlab/cycle_analytics/issue_stage.rb
+6
-8
lib/gitlab/cycle_analytics/metrics_fetcher.rb
lib/gitlab/cycle_analytics/metrics_fetcher.rb
+1
-1
lib/gitlab/cycle_analytics/plan_stage.rb
lib/gitlab/cycle_analytics/plan_stage.rb
+6
-8
lib/gitlab/cycle_analytics/production_stage.rb
lib/gitlab/cycle_analytics/production_stage.rb
+5
-7
lib/gitlab/cycle_analytics/review_stage.rb
lib/gitlab/cycle_analytics/review_stage.rb
+5
-7
lib/gitlab/cycle_analytics/stage.rb
lib/gitlab/cycle_analytics/stage.rb
+9
-0
lib/gitlab/cycle_analytics/staging_stage.rb
lib/gitlab/cycle_analytics/staging_stage.rb
+5
-7
lib/gitlab/cycle_analytics/test_stage.rb
lib/gitlab/cycle_analytics/test_stage.rb
+5
-7
spec/lib/gitlab/cycle_analytics/events_spec.rb
spec/lib/gitlab/cycle_analytics/events_spec.rb
+1
-1
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
+1
-1
spec/serializers/analytics_stage_serializer_spec.rb
spec/serializers/analytics_stage_serializer_spec.rb
+1
-1
No files found.
app/controllers/projects/cycle_analytics/events_controller.rb
View file @
b8056669
...
@@ -9,33 +9,33 @@ module Projects
...
@@ -9,33 +9,33 @@ module Projects
before_action
:authorize_read_merge_request!
,
only:
[
:code
,
:review
]
before_action
:authorize_read_merge_request!
,
only:
[
:code
,
:review
]
def
issue
def
issue
render_events
(
cycle_analytics
.
events_for
(
:issue
)
)
render_events
(
cycle_analytics
[
:issue
].
events
)
end
end
def
plan
def
plan
render_events
(
cycle_analytics
.
events_for
(
:plan
)
)
render_events
(
cycle_analytics
[
:plan
].
events
)
end
end
def
code
def
code
render_events
(
cycle_analytics
.
events_for
(
:code
)
)
render_events
(
cycle_analytics
[
:code
].
events
)
end
end
def
test
def
test
options
(
events_params
)[
:branch
]
=
events_params
[
:branch_name
]
options
(
events_params
)[
:branch
]
=
events_params
[
:branch_name
]
render_events
(
cycle_analytics
.
events_for
(
:test
)
)
render_events
(
cycle_analytics
[
:test
].
events
)
end
end
def
review
def
review
render_events
(
cycle_analytics
.
events_for
(
:review
)
)
render_events
(
cycle_analytics
[
:review
].
events
)
end
end
def
staging
def
staging
render_events
(
cycle_analytics
.
events_for
(
:staging
)
)
render_events
(
cycle_analytics
[
:staging
].
events
)
end
end
def
production
def
production
render_events
(
cycle_analytics
.
events_for
(
:production
)
)
render_events
(
cycle_analytics
[
:production
].
events
)
end
end
private
private
...
@@ -54,7 +54,7 @@ module Projects
...
@@ -54,7 +54,7 @@ module Projects
def
events_params
def
events_params
return
{}
unless
params
[
:events
].
present?
return
{}
unless
params
[
:events
].
present?
params
[
:events
].
slice
(
:start_date
,
:branch_name
)
params
[
:events
].
permit
(
:start_date
,
:branch_name
)
end
end
end
end
end
end
...
...
app/controllers/projects/cycle_analytics_controller.rb
View file @
b8056669
...
@@ -6,7 +6,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
...
@@ -6,7 +6,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
before_action
:authorize_read_cycle_analytics!
before_action
:authorize_read_cycle_analytics!
def
show
def
show
@cycle_analytics
=
::
CycleAnalytics
.
new
(
@project
,
options
:
options
(
cycle_analytics_params
))
@cycle_analytics
=
::
CycleAnalytics
.
new
(
@project
,
options
(
cycle_analytics_params
))
@cycle_analytics_no_data
=
@cycle_analytics
.
no_stats?
@cycle_analytics_no_data
=
@cycle_analytics
.
no_stats?
...
@@ -21,7 +21,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
...
@@ -21,7 +21,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
def
cycle_analytics_params
def
cycle_analytics_params
return
{}
unless
params
[
:cycle_analytics
].
present?
return
{}
unless
params
[
:cycle_analytics
].
present?
params
[
:cycle_analytics
].
slice
(
:start_date
)
params
[
:cycle_analytics
].
permit
(
:start_date
)
end
end
def
cycle_analytics_json
def
cycle_analytics_json
...
...
app/models/cycle_analytics.rb
View file @
b8056669
class
CycleAnalytics
class
CycleAnalytics
STAGES
=
%i[issue plan code test review staging production]
.
freeze
STAGES
=
%i[issue plan code test review staging production]
.
freeze
def
initialize
(
project
,
options
:
)
def
initialize
(
project
,
options
)
@project
=
project
@project
=
project
@options
=
options
@options
=
options
end
end
...
@@ -22,19 +22,15 @@ class CycleAnalytics
...
@@ -22,19 +22,15 @@ class CycleAnalytics
Gitlab
::
CycleAnalytics
::
Permissions
.
get
(
user:
user
,
project:
@project
)
Gitlab
::
CycleAnalytics
::
Permissions
.
get
(
user:
user
,
project:
@project
)
end
end
def
events_for
(
stag
e
)
def
[]
(
stage_nam
e
)
classify_stage
(
stage
).
new
(
project:
@project
,
options:
@options
,
stage:
stage
).
events
Gitlab
::
CycleAnalytics
::
Stage
[
stage_name
].
new
(
project:
@project
,
options:
@options
)
end
end
private
private
def
stats_per_stage
def
stats_per_stage
STAGES
.
map
do
|
stage_name
|
STAGES
.
map
do
|
stage_name
|
classify_stage
(
stage_name
).
new
(
project:
@project
,
options:
@options
,
stage:
stage_name
).
median_data
Gitlab
::
CycleAnalytics
::
Stage
[
stage_name
].
new
(
project:
@project
,
options:
@options
).
median_data
end
end
end
end
def
classify_stage
(
stage_name
)
"Gitlab::CycleAnalytics::
#{
stage_name
.
to_s
.
capitalize
}
Stage"
.
constantize
end
end
end
app/serializers/analytics_stage_entity.rb
View file @
b8056669
class
AnalyticsStageEntity
<
Grape
::
Entity
class
AnalyticsStageEntity
<
Grape
::
Entity
include
EntityDateHelper
include
EntityDateHelper
expose
:stage
,
as: :title
do
|
object
|
expose
:title
object
.
stage
.
to_s
.
capitalize
end
expose
:description
expose
:description
expose
:median
,
as: :value
do
|
stage
|
expose
:median
,
as: :value
do
|
stage
|
...
...
lib/gitlab/cycle_analytics/base_event.rb
View file @
b8056669
...
@@ -2,13 +2,13 @@ module Gitlab
...
@@ -2,13 +2,13 @@ module Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
BaseEvent
class
BaseEvent
include
MetricsTables
include
MetricsTables
include
ClassNameUtil
attr_reader
:sta
ge
,
:sta
rt_time_attrs
,
:end_time_attrs
,
:projections
,
:query
attr_reader
:start_time_attrs
,
:end_time_attrs
,
:projections
,
:query
def
initialize
(
fetcher
:,
stage
:,
options
:)
def
initialize
(
fetcher
:,
options
:)
@query
=
EventsQuery
.
new
(
fetcher:
fetcher
)
@query
=
EventsQuery
.
new
(
fetcher:
fetcher
)
@project
=
fetcher
.
project
@project
=
fetcher
.
project
@stage
=
stage
@options
=
options
@options
=
options
end
end
...
@@ -26,6 +26,10 @@ module Gitlab
...
@@ -26,6 +26,10 @@ module Gitlab
@order
||
@start_time_attrs
@order
||
@start_time_attrs
end
end
def
stage
class_name_for
(
'Event'
)
end
private
private
def
update_author!
def
update_author!
...
...
lib/gitlab/cycle_analytics/base_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
BaseStage
class
BaseStage
attr_reader
:stage
,
:description
include
ClassNameUtil
def
initialize
(
project
:,
options
:
,
stage
:
)
def
initialize
(
project
:,
options
:)
@project
=
project
@project
=
project
@options
=
options
@options
=
options
@fetcher
=
Gitlab
::
CycleAnalytics
::
MetricsFetcher
.
new
(
project:
project
,
@fetcher
=
Gitlab
::
CycleAnalytics
::
MetricsFetcher
.
new
(
project:
project
,
from:
options
[
:from
],
from:
options
[
:from
],
branch:
options
[
:branch
])
branch:
options
[
:branch
])
@stage
=
stage
end
end
def
events
def
events
event_class
.
new
(
fetcher:
@fetcher
,
stage:
@stage
,
options:
@options
).
fetch
Gitlab
::
CycleAnalytics
::
Event
[
stage
].
new
(
fetcher:
@fetcher
,
options:
@options
).
fetch
end
end
def
median_data
def
median_data
AnalyticsStageSerializer
.
new
.
represent
(
self
).
as_json
AnalyticsStageSerializer
.
new
.
represent
(
self
).
as_json
end
end
def
title
stage
.
to_s
.
capitalize
end
def
median
raise
NotImplementedError
.
new
(
"Expected
#{
self
.
name
}
to implement median"
)
end
private
private
def
event_class
def
stage
"Gitlab::CycleAnalytics::
#{
@stage
.
to_s
.
capitalize
}
Event"
.
constantize
class_name_for
(
'Stage'
)
end
end
end
end
end
end
...
...
lib/gitlab/cycle_analytics/class_name_util.rb
0 → 100644
View file @
b8056669
module
Gitlab
module
CycleAnalytics
module
ClassNameUtil
def
class_name_for
(
type
)
class_name
.
split
(
type
).
first
.
to_sym
end
def
class_name
self
.
class
.
name
.
demodulize
end
end
end
end
lib/gitlab/cycle_analytics/code_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
CodeStage
<
BaseStage
class
CodeStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"Time until first merge request"
@description
=
"Time until first merge request"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:code
,
@fetcher
.
median
(
:code
,
Issue
::
Metrics
.
arel_table
[
:first_mentioned_in_commit_at
],
Issue
::
Metrics
.
arel_table
[
:first_mentioned_in_commit_at
],
MergeRequest
.
arel_table
[
:created_at
])
MergeRequest
.
arel_table
[
:created_at
])
end
end
...
...
lib/gitlab/cycle_analytics/event.rb
0 → 100644
View file @
b8056669
module
Gitlab
module
CycleAnalytics
module
Event
def
self
.
[]
(
stage_name
)
const_get
(
"::Gitlab::CycleAnalytics::
#{
stage_name
.
to_s
.
camelize
}
Event"
)
end
end
end
end
lib/gitlab/cycle_analytics/issue_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
IssueStage
<
BaseStage
class
IssueStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"Time before an issue gets scheduled"
@description
=
"Time before an issue gets scheduled"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:issue
,
@fetcher
.
median
(
:issue
,
Issue
.
arel_table
[
:created_at
],
Issue
.
arel_table
[
:created_at
],
[
Issue
::
Metrics
.
arel_table
[
:first_associated_with_milestone_at
],
[
Issue
::
Metrics
.
arel_table
[
:first_associated_with_milestone_at
],
Issue
::
Metrics
.
arel_table
[
:first_added_to_board_at
]])
Issue
::
Metrics
.
arel_table
[
:first_added_to_board_at
]])
...
...
lib/gitlab/cycle_analytics/metrics_fetcher.rb
View file @
b8056669
...
@@ -15,7 +15,7 @@ module Gitlab
...
@@ -15,7 +15,7 @@ module Gitlab
@branch
=
branch
@branch
=
branch
end
end
def
calculate_metric
(
name
,
start_time_attrs
,
end_time_attrs
)
def
median
(
name
,
start_time_attrs
,
end_time_attrs
)
cte_table
=
Arel
::
Table
.
new
(
"cte_table_for_
#{
name
}
"
)
cte_table
=
Arel
::
Table
.
new
(
"cte_table_for_
#{
name
}
"
)
# Build a `SELECT` query. We find the first of the `end_time_attrs` that isn't `NULL` (call this end_time).
# Build a `SELECT` query. We find the first of the `end_time_attrs` that isn't `NULL` (call this end_time).
...
...
lib/gitlab/cycle_analytics/plan_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
PlanStage
<
BaseStage
class
PlanStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"Time before an issue starts implementation"
@description
=
"Time before an issue starts implementation"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:plan
,
@fetcher
.
median
(
:plan
,
[
Issue
::
Metrics
.
arel_table
[
:first_associated_with_milestone_at
],
[
Issue
::
Metrics
.
arel_table
[
:first_associated_with_milestone_at
],
Issue
::
Metrics
.
arel_table
[
:first_added_to_board_at
]],
Issue
::
Metrics
.
arel_table
[
:first_added_to_board_at
]],
Issue
::
Metrics
.
arel_table
[
:first_mentioned_in_commit_at
])
Issue
::
Metrics
.
arel_table
[
:first_mentioned_in_commit_at
])
...
...
lib/gitlab/cycle_analytics/production_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
ProductionStage
<
BaseStage
class
ProductionStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"From issue creation until deploy to production"
@description
=
"From issue creation until deploy to production"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:production
,
@fetcher
.
median
(
:production
,
Issue
.
arel_table
[
:created_at
],
Issue
.
arel_table
[
:created_at
],
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
end
end
...
...
lib/gitlab/cycle_analytics/review_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
ReviewStage
<
BaseStage
class
ReviewStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"Time between merge request creation and merge/close"
@description
=
"Time between merge request creation and merge/close"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:review
,
@fetcher
.
median
(
:review
,
MergeRequest
.
arel_table
[
:created_at
],
MergeRequest
.
arel_table
[
:created_at
],
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
])
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
])
end
end
...
...
lib/gitlab/cycle_analytics/stage.rb
0 → 100644
View file @
b8056669
module
Gitlab
module
CycleAnalytics
module
Stage
def
self
.
[]
(
stage_name
)
const_get
(
"::Gitlab::CycleAnalytics::
#{
stage_name
.
to_s
.
camelize
}
Stage"
)
end
end
end
end
lib/gitlab/cycle_analytics/staging_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
StagingStage
<
BaseStage
class
StagingStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"From merge request merge until deploy to production"
@description
=
"From merge request merge until deploy to production"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:staging
,
@fetcher
.
median
(
:staging
,
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
],
MergeRequest
::
Metrics
.
arel_table
[
:merged_at
],
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
MergeRequest
::
Metrics
.
arel_table
[
:first_deployed_to_production_at
])
end
end
...
...
lib/gitlab/cycle_analytics/test_stage.rb
View file @
b8056669
module
Gitlab
module
Gitlab
module
CycleAnalytics
module
CycleAnalytics
class
TestStage
<
BaseStage
class
TestStage
<
BaseStage
def
initialize
(
*
args
)
def
description
super
(
*
args
)
"Total test time for all commits/merges"
@description
=
"Total test time for all commits/merges"
end
end
def
median
def
median
@fetcher
.
calculate_metric
(
:test
,
@fetcher
.
median
(
:test
,
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_started_at
],
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_started_at
],
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_finished_at
])
MergeRequest
::
Metrics
.
arel_table
[
:latest_build_finished_at
])
end
end
...
...
spec/lib/gitlab/cycle_analytics/events_spec.rb
View file @
b8056669
...
@@ -7,7 +7,7 @@ describe 'cycle analytics events' do
...
@@ -7,7 +7,7 @@ describe 'cycle analytics events' do
let!
(
:context
)
{
create
(
:issue
,
project:
project
,
created_at:
2
.
days
.
ago
)
}
let!
(
:context
)
{
create
(
:issue
,
project:
project
,
created_at:
2
.
days
.
ago
)
}
let
(
:events
)
do
let
(
:events
)
do
CycleAnalytics
.
new
(
project
,
options:
{
from:
from_date
,
current_user:
user
}).
events_for
(
stage
)
CycleAnalytics
.
new
(
project
,
{
from:
from_date
,
current_user:
user
})[
stage
].
events
end
end
before
do
before
do
...
...
spec/lib/gitlab/cycle_analytics/shared_stage_spec.rb
View file @
b8056669
...
@@ -4,7 +4,7 @@ shared_examples 'base stage' do
...
@@ -4,7 +4,7 @@ shared_examples 'base stage' do
let
(
:stage
)
{
described_class
.
new
(
project:
double
,
options:
{},
stage:
stage_name
)
}
let
(
:stage
)
{
described_class
.
new
(
project:
double
,
options:
{},
stage:
stage_name
)
}
before
do
before
do
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
MetricsFetcher
).
to
receive
(
:
calculate_metric
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
MetricsFetcher
).
to
receive
(
:
median
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEvent
).
to
receive
(
:event_result
).
and_return
({})
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEvent
).
to
receive
(
:event_result
).
and_return
({})
end
end
...
...
spec/serializers/analytics_stage_serializer_spec.rb
View file @
b8056669
...
@@ -10,7 +10,7 @@ describe AnalyticsStageSerializer do
...
@@ -10,7 +10,7 @@ describe AnalyticsStageSerializer do
let
(
:resource
)
{
Gitlab
::
CycleAnalytics
::
CodeStage
.
new
(
project:
double
,
options:
{},
stage: :code
)
}
let
(
:resource
)
{
Gitlab
::
CycleAnalytics
::
CodeStage
.
new
(
project:
double
,
options:
{},
stage: :code
)
}
before
do
before
do
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
MetricsFetcher
).
to
receive
(
:
calculate_metric
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
MetricsFetcher
).
to
receive
(
:
median
).
and_return
(
1.12
)
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEvent
).
to
receive
(
:event_result
).
and_return
({})
allow_any_instance_of
(
Gitlab
::
CycleAnalytics
::
BaseEvent
).
to
receive
(
:event_result
).
and_return
({})
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment