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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
babf667b
Commit
babf667b
authored
Apr 21, 2020
by
nmilojevic1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move measurement to service layer
- Fix specs - Add to ImportService - Fix rake tasks
parent
ba00a5aa
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
187 additions
and
34 deletions
+187
-34
app/services/projects/gitlab_projects_import_service.rb
app/services/projects/gitlab_projects_import_service.rb
+32
-6
ee/app/services/ee/projects/gitlab_projects_import_service.rb
...pp/services/ee/projects/gitlab_projects_import_service.rb
+1
-1
lib/gitlab/import_export/project/base_task.rb
lib/gitlab/import_export/project/base_task.rb
+7
-0
lib/gitlab/import_export/project/import_task.rb
lib/gitlab/import_export/project/import_task.rb
+11
-7
lib/gitlab/utils/measuring.rb
lib/gitlab/utils/measuring.rb
+40
-17
spec/lib/gitlab/utils/measuring_spec.rb
spec/lib/gitlab/utils/measuring_spec.rb
+41
-0
spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb
...ervices/gitlab_projects_import_service_shared_examples.rb
+52
-0
spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb
.../tasks/gitlab/import_export/measurable_shared_examples.rb
+3
-3
No files found.
app/services/projects/gitlab_projects_import_service.rb
View file @
babf667b
...
...
@@ -14,32 +14,58 @@ module Projects
@current_user
,
@params
,
@override_params
=
user
,
import_params
.
dup
,
override_params
end
def
execute
prepare_template_environment
(
template_file
)
def
execute
(
options
=
{})
measurement_enabled
=
!!
options
[
:measurement_enabled
]
measurement_logger
=
options
[
:measurement_logger
]
prepare_import_params
::
Gitlab
::
Utils
::
Measuring
.
execute_with
(
measurement_enabled
,
measurement_logger
,
base_data
)
do
prepare_template_environment
(
template_file
)
::
Projects
::
CreateService
.
new
(
current_user
,
params
).
execute
prepare_import_params
::
Projects
::
CreateService
.
new
(
current_user
,
params
).
execute
end
end
private
def
base_data
base_data
=
{
class:
self
.
class
.
name
,
current_user:
current_user
.
name
,
project_full_path:
project_path
}
if
template_file
base_data
[
:import_type
]
=
'gitlab_project'
base_data
[
:file_path
]
=
template_file
.
path
end
base_data
end
def
overwrite_project?
overwrite?
&&
project_with_same_full_path?
end
def
project_with_same_full_path?
Project
.
find_by_full_path
(
"
#{
current_namespace
.
full_path
}
/
#{
params
[
:path
]
}
"
).
present?
Project
.
find_by_full_path
(
project_path
).
present?
end
# rubocop: disable CodeReuse/ActiveRecord
def
current_namespace
strong_memoize
(
:current_namespace
)
do
Namespace
.
find_by
(
id:
params
[
:namespace_id
])
Namespace
.
find_by
(
id:
params
[
:namespace_id
])
||
current_user
.
namespace
end
end
# rubocop: enable CodeReuse/ActiveRecord
def
project_path
strong_memoize
(
:project_path
)
do
"
#{
current_namespace
.
full_path
}
/
#{
params
[
:path
]
}
"
end
end
def
overwrite?
strong_memoize
(
:overwrite
)
do
params
.
delete
(
:overwrite
)
...
...
ee/app/services/ee/projects/gitlab_projects_import_service.rb
View file @
babf667b
...
...
@@ -7,7 +7,7 @@ module EE
include
::
Gitlab
::
Utils
::
StrongMemoize
override
:execute
def
execute
def
execute
(
options
=
{})
super
.
tap
do
|
project
|
if
project
.
saved?
&&
custom_template
custom_template
.
add_export_job
(
current_user:
current_user
,
...
...
lib/gitlab/import_export/project/base_task.rb
View file @
babf667b
...
...
@@ -30,6 +30,13 @@ module Gitlab
true
end
def
measurement_options
{
measurement_enabled:
measurement_enabled?
,
measurement_logger:
logger
}
end
def
error
(
message
)
logger
.
error
(
message
)
...
...
lib/gitlab/import_export/project/import_task.rb
View file @
babf667b
...
...
@@ -32,7 +32,7 @@ module Gitlab
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24475#note_283090635
# For development setups, this code-path will be excluded from n+1 detection.
::
Gitlab
::
GitalyClient
.
allow_n_plus_1_calls
do
measurement_enabled?
?
measurement
.
with_measuring
{
yield
}
:
yield
yield
end
end
...
...
@@ -56,14 +56,10 @@ module Gitlab
disable_upload_object_storage
do
service
=
Projects
::
GitlabProjectsImportService
.
new
(
current_user
,
{
namespace_id:
namespace
.
id
,
path:
project_path
,
file:
File
.
open
(
file_path
)
}
import_params
)
service
.
execute
service
.
execute
(
measurement_options
)
end
end
...
...
@@ -99,6 +95,14 @@ module Gitlab
" as
#{
current_user
.
name
}
"
end
def
import_params
{
namespace_id:
namespace
.
id
,
path:
project_path
,
file:
File
.
open
(
file_path
)
}
end
def
show_import_failures_count
return
unless
project
.
import_failures
.
exists?
...
...
lib/gitlab/utils/measuring.rb
View file @
babf667b
...
...
@@ -5,13 +5,25 @@ require 'prometheus/pid_provider'
module
Gitlab
module
Utils
class
Measuring
def
initialize
(
logger:
Logger
.
new
(
$stdout
))
@logger
=
logger
class
<<
self
def
execute_with
(
measurement_enabled
,
logger
,
base_data
)
measurement_enabled
?
measuring
(
logger
,
base_data
).
with_measuring
{
yield
}
:
yield
end
private
def
measuring
(
logger
,
base_data
)
Gitlab
::
Utils
::
Measuring
.
new
(
logger:
logger
,
base_data:
base_data
)
end
end
def
initialize
(
logger:
nil
,
base_data:
{})
@logger
=
logger
||
Logger
.
new
(
$stdout
)
@base_data
=
base_data
end
def
with_measuring
logger
.
info
"Measuring enabled..."
with_gc_stats
do
result
=
with_gc_stats
do
with_count_queries
do
with_measure_time
do
yield
...
...
@@ -19,45 +31,56 @@ module Gitlab
end
end
logger
.
info
"Memory usage:
#{
Gitlab
::
Metrics
::
System
.
memory_usage
.
to_f
/
1024
/
1024
}
MiB"
logger
.
info
"Label:
#{
::
Prometheus
::
PidProvider
.
worker_id
}
"
log_info
(
gc_stats:
@gc_stats
,
time_to_finish:
@time_to_finish
,
number_of_sql_calls:
@count
,
memory_usage:
"
#{
Gitlab
::
Metrics
::
System
.
memory_usage
.
to_f
/
1024
/
1024
}
MiB"
,
label:
::
Prometheus
::
PidProvider
.
worker_id
)
result
end
private
attr_reader
:logger
attr_reader
:logger
,
:base_data
def
with_count_queries
(
&
block
)
count
=
0
@
count
=
0
counter_f
=
->
(
_name
,
_started
,
_finished
,
_unique_id
,
payload
)
{
count
+=
1
unless
payload
[
:name
].
in?
%w[CACHE SCHEMA]
@
count
+=
1
unless
payload
[
:name
].
in?
%w[CACHE SCHEMA]
}
ActiveSupport
::
Notifications
.
subscribed
(
counter_f
,
"sql.active_record"
,
&
block
)
end
logger
.
info
"Number of sql calls:
#{
count
}
"
def
log_info
(
details
)
details
=
base_data
.
merge
(
details
)
details
=
details
.
to_yaml
if
ActiveSupport
::
Logger
.
logger_outputs_to?
(
logger
,
STDOUT
)
logger
.
info
(
details
)
end
def
with_gc_stats
GC
.
start
# perform a full mark-and-sweep
stats_before
=
GC
.
stat
yield
result
=
yield
stats_after
=
GC
.
stat
stats_diff
=
stats_after
.
map
do
|
key
,
after_value
|
@gc_stats
=
stats_after
.
map
do
|
key
,
after_value
|
before_value
=
stats_before
[
key
]
[
key
,
before:
before_value
,
after:
after_value
,
diff:
after_value
-
before_value
]
end
.
to_h
logger
.
info
"GC stats:"
logger
.
info
JSON
.
pretty_generate
(
stats_diff
)
result
end
def
with_measure_time
timing
=
Benchmark
.
realtime
do
yield
result
=
0
@time_to_finish
=
Benchmark
.
realtime
do
result
=
yield
end
logger
.
info
"Time to finish:
#{
duration_in_numbers
(
timing
)
}
"
result
end
def
duration_in_numbers
(
duration_in_seconds
)
...
...
spec/lib/gitlab/utils/measuring_spec.rb
0 → 100644
View file @
babf667b
# frozen_string_literal: true
require
'fast_spec_helper'
describe
Gitlab
::
Utils
::
Measuring
do
describe
'#with_measuring'
do
let
(
:logger
)
{
double
(
:logger
)
}
let
(
:base_data
)
{
{}
}
let
(
:result
)
{
"result"
}
before
do
allow
(
logger
).
to
receive
(
:info
)
end
let
(
:measurement
)
{
described_class
.
new
(
logger:
logger
,
base_data:
base_data
)
}
subject
do
measurement
.
with_measuring
{
result
}
end
it
'measures and logs data'
,
:aggregate_failure
do
expect
(
measurement
).
to
receive
(
:with_measure_time
).
and_call_original
expect
(
measurement
).
to
receive
(
:with_count_queries
).
and_call_original
expect
(
measurement
).
to
receive
(
:with_gc_stats
).
and_call_original
expect
(
logger
).
to
receive
(
:info
).
with
(
including
(
:gc_stats
,
:time_to_finish
,
:number_of_sql_calls
,
:memory_usage
,
:label
))
is_expected
.
to
eq
(
result
)
end
context
'with base_data provided'
do
let
(
:base_data
)
{
{
test:
"data"
}
}
it
'logs includes base data'
do
expect
(
logger
).
to
receive
(
:info
).
with
(
including
(
:test
,
:gc_stats
,
:time_to_finish
,
:number_of_sql_calls
,
:memory_usage
,
:label
))
subject
end
end
end
end
spec/support/shared_examples/services/gitlab_projects_import_service_shared_examples.rb
View file @
babf667b
...
...
@@ -53,4 +53,56 @@ RSpec.shared_examples 'gitlab projects import validations' do
end
end
end
context
'when measurable params are provided'
do
let
(
:base_data
)
do
base_data
=
{
class:
described_class
.
name
,
current_user:
namespace
.
owner
.
name
,
project_full_path:
"
#{
namespace
.
full_path
}
/
#{
path
}
"
}
base_data
.
merge!
({
import_type:
'gitlab_project'
,
file_path:
import_params
[
:file
].
path
})
if
import_params
[
:file
]
base_data
end
subject
{
described_class
.
new
(
namespace
.
owner
,
import_params
)
}
context
'when measurement is enabled'
do
let
(
:logger
)
{
double
(
:logger
)
}
let
(
:measurable_options
)
do
{
measurement_enabled:
true
,
measurement_logger:
logger
}
end
before
do
allow
(
logger
).
to
receive
(
:info
)
end
it
'measure service execution with Gitlab::Utils::Measuring'
do
expect
(
Gitlab
::
Utils
::
Measuring
).
to
receive
(
:execute_with
).
with
(
true
,
logger
,
base_data
).
and_call_original
expect_next_instance_of
(
Gitlab
::
Utils
::
Measuring
)
do
|
measuring
|
expect
(
measuring
).
to
receive
(
:with_measuring
).
and_call_original
end
subject
.
execute
(
measurable_options
)
end
end
context
'when measurement is disabled'
do
let
(
:measurable_options
)
do
{
measurement_enabled:
false
,
}
end
it
'does not measure service execution'
do
expect
(
Gitlab
::
Utils
::
Measuring
).
to
receive
(
:execute_with
).
with
(
false
,
nil
,
base_data
).
and_call_original
expect
(
Gitlab
::
Utils
::
Measuring
).
not_to
receive
(
:new
)
subject
.
execute
(
measurable_options
)
end
end
end
end
spec/support/shared_examples/tasks/gitlab/import_export/measurable_shared_examples.rb
View file @
babf667b
...
...
@@ -5,7 +5,7 @@ RSpec.shared_examples 'measurable' do
let
(
:measurement_enabled
)
{
true
}
it
'prints measurement results'
do
expect
{
subject
}.
to
output
(
including
(
'Measuring enabled...'
,
'Number of sql calls:'
,
'GC stats:'
)).
to_stdout
expect
{
subject
}.
to
output
(
including
(
"time_to_finish"
)).
to_stdout
end
end
...
...
@@ -13,7 +13,7 @@ RSpec.shared_examples 'measurable' do
let
(
:measurement_enabled
)
{
false
}
it
'does not output measurement results'
do
expect
{
subject
}.
not_to
output
(
/
Measuring enabled...
/
).
to_stdout
expect
{
subject
}.
not_to
output
(
/
time_to_finish
/
).
to_stdout
end
end
...
...
@@ -21,7 +21,7 @@ RSpec.shared_examples 'measurable' do
let
(
:measurement_enabled
)
{
nil
}
it
'does not output measurement results'
do
expect
{
subject
}.
not_to
output
(
/
Measuring enabled...
/
).
to_stdout
expect
{
subject
}.
not_to
output
(
/
time_to_finish
/
).
to_stdout
end
it
'does not raise any exception'
do
...
...
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