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
a8e34125
Commit
a8e34125
authored
Mar 08, 2018
by
Bob Van Landuyt
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into ce-to-ee-2018-03-08
parents
f8fdb263
73463b08
Changes
68
Show whitespace changes
Inline
Side-by-side
Showing
68 changed files
with
2006 additions
and
36 deletions
+2006
-36
app/assets/stylesheets/pages/settings.scss
app/assets/stylesheets/pages/settings.scss
+18
-8
app/controllers/projects/prometheus/metrics_controller.rb
app/controllers/projects/prometheus/metrics_controller.rb
+77
-0
app/models/concerns/prometheus_adapter.rb
app/models/concerns/prometheus_adapter.rb
+7
-1
app/models/project.rb
app/models/project.rb
+2
-0
app/views/projects/services/prometheus/_show.html.haml
app/views/projects/services/prometheus/_show.html.haml
+26
-2
app/workers/all_queues.yml
app/workers/all_queues.yml
+2
-0
config/initializers/1_settings.rb
config/initializers/1_settings.rb
+3
-0
config/routes/project.rb
config/routes/project.rb
+2
-1
db/schema.rb
db/schema.rb
+23
-0
ee/app/assets/javascripts/geo_nodes/components/geo_node_details.vue
...ets/javascripts/geo_nodes/components/geo_node_details.vue
+32
-0
ee/app/assets/javascripts/geo_nodes/store/geo_nodes_store.js
ee/app/assets/javascripts/geo_nodes/store/geo_nodes_store.js
+10
-0
ee/app/assets/javascripts/pages/projects/services/edit/index.js
.../assets/javascripts/pages/projects/services/edit/index.js
+13
-0
ee/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
...sets/javascripts/prometheus_metrics/prometheus_metrics.js
+103
-0
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
...javascripts/vue_merge_request_widget/mr_widget_options.js
+2
-0
ee/app/controllers/ee/admin/logs_controller.rb
ee/app/controllers/ee/admin/logs_controller.rb
+2
-1
ee/app/finders/geo/project_registry_finder.rb
ee/app/finders/geo/project_registry_finder.rb
+175
-10
ee/app/finders/geo/repository_verification_finder.rb
ee/app/finders/geo/repository_verification_finder.rb
+16
-0
ee/app/models/ee/project.rb
ee/app/models/ee/project.rb
+6
-1
ee/app/models/geo/fdw/project_repository_state.rb
ee/app/models/geo/fdw/project_repository_state.rb
+7
-0
ee/app/models/geo/project_registry.rb
ee/app/models/geo/project_registry.rb
+37
-0
ee/app/models/geo_node_status.rb
ee/app/models/geo_node_status.rb
+24
-0
ee/app/models/project_repository_state.rb
ee/app/models/project_repository_state.rb
+12
-1
ee/app/models/prometheus_metric.rb
ee/app/models/prometheus_metric.rb
+36
-0
ee/app/serializers/prometheus_metric_entity.rb
ee/app/serializers/prometheus_metric_entity.rb
+14
-0
ee/app/serializers/prometheus_metric_serializer.rb
ee/app/serializers/prometheus_metric_serializer.rb
+3
-0
ee/app/services/geo/base_sync_service.rb
ee/app/services/geo/base_sync_service.rb
+5
-0
ee/app/services/geo/repository_verify_secondary_service.rb
ee/app/services/geo/repository_verify_secondary_service.rb
+106
-0
ee/app/views/projects/prometheus/metrics/_form.html.haml
ee/app/views/projects/prometheus/metrics/_form.html.haml
+59
-0
ee/app/views/projects/prometheus/metrics/edit.html.haml
ee/app/views/projects/prometheus/metrics/edit.html.haml
+6
-0
ee/app/views/projects/prometheus/metrics/new.html.haml
ee/app/views/projects/prometheus/metrics/new.html.haml
+6
-0
ee/app/workers/geo/repository_verification/secondary/scheduler_worker.rb
...geo/repository_verification/secondary/scheduler_worker.rb
+37
-0
ee/app/workers/geo/repository_verification/secondary/single_worker.rb
...rs/geo/repository_verification/secondary/single_worker.rb
+46
-0
ee/changelogs/unreleased/geo-repository-checksum.yml
ee/changelogs/unreleased/geo-repository-checksum.yml
+5
-0
ee/changelogs/unreleased/pawel-prometheus-business-metrics-ee-2273.yml
.../unreleased/pawel-prometheus-business-metrics-ee-2273.yml
+5
-0
ee/db/geo/migrate/20180201154345_add_repository_verification_to_project_registry.rb
...154345_add_repository_verification_to_project_registry.rb
+18
-0
ee/db/geo/schema.rb
ee/db/geo/schema.rb
+9
-1
ee/db/migrate/20180101160629_create_prometheus_metrics.rb
ee/db/migrate/20180101160629_create_prometheus_metrics.rb
+16
-0
ee/db/migrate/20180225180932_add_geo_node_verification_status.rb
...igrate/20180225180932_add_geo_node_verification_status.rb
+13
-0
ee/lib/ee/api/entities.rb
ee/lib/ee/api/entities.rb
+12
-0
ee/lib/gitlab/geo/cron_manager.rb
ee/lib/gitlab/geo/cron_manager.rb
+1
-0
ee/lib/gitlab/geo/log_helpers.rb
ee/lib/gitlab/geo/log_helpers.rb
+6
-2
ee/lib/gitlab/geo/repository_verification_log_helpers.rb
ee/lib/gitlab/geo/repository_verification_log_helpers.rb
+13
-0
ee/lib/gitlab/geo/repository_verification_logger.rb
ee/lib/gitlab/geo/repository_verification_logger.rb
+9
-0
ee/lib/gitlab/prometheus/queries/validate_query.rb
ee/lib/gitlab/prometheus/queries/validate_query.rb
+19
-0
ee/spec/controllers/projects/prometheus/metrics_controller_spec.rb
...ontrollers/projects/prometheus/metrics_controller_spec.rb
+119
-0
ee/spec/factories/geo/project_registry.rb
ee/spec/factories/geo/project_registry.rb
+26
-0
ee/spec/factories/prometheus_metrics.rb
ee/spec/factories/prometheus_metrics.rb
+11
-0
ee/spec/finders/geo/project_registry_finder_spec.rb
ee/spec/finders/geo/project_registry_finder_spec.rb
+235
-0
ee/spec/fixtures/api/schemas/prometheus/metrics.json
ee/spec/fixtures/api/schemas/prometheus/metrics.json
+28
-0
ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json
...c/fixtures/api/schemas/public_api/v4/geo_node_status.json
+12
-0
ee/spec/lib/gitlab/geo/cron_manager_spec.rb
ee/spec/lib/gitlab/geo/cron_manager_spec.rb
+3
-1
ee/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
ee/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
+32
-0
ee/spec/models/geo/project_registry_spec.rb
ee/spec/models/geo/project_registry_spec.rb
+48
-0
ee/spec/models/prometheus_metric_spec.rb
ee/spec/models/prometheus_metric_spec.rb
+58
-0
ee/spec/services/ci_cd/github_setup_service_spec.rb
ee/spec/services/ci_cd/github_setup_service_spec.rb
+9
-1
ee/spec/services/geo/repository_verify_secondary_service_spec.rb
.../services/geo/repository_verify_secondary_service_spec.rb
+161
-0
lib/gitlab/import_export/import_export.yml
lib/gitlab/import_export/import_export.yml
+1
-0
lib/gitlab/prometheus/metric_group.rb
lib/gitlab/prometheus/metric_group.rb
+8
-3
locale/gitlab.pot
locale/gitlab.pot
+14
-0
spec/features/projects/merge_requests/user_creates_merge_request_spec.rb
...rojects/merge_requests/user_creates_merge_request_spec.rb
+4
-2
spec/javascripts/geo_nodes/mock_data.js
spec/javascripts/geo_nodes/mock_data.js
+6
-0
spec/javascripts/prometheus_metrics/ee/mock_data.js
spec/javascripts/prometheus_metrics/ee/mock_data.js
+23
-0
spec/javascripts/prometheus_metrics/ee/prometheus_metrics_spec.js
...ascripts/prometheus_metrics/ee/prometheus_metrics_spec.js
+83
-0
spec/lib/gitlab/import_export/all_models.yml
spec/lib/gitlab/import_export/all_models.yml
+3
-0
spec/lib/gitlab/import_export/safe_model_attributes.yml
spec/lib/gitlab/import_export/safe_model_attributes.yml
+11
-0
spec/models/concerns/prometheus_adapter_spec.rb
spec/models/concerns/prometheus_adapter_spec.rb
+23
-0
spec/serializers/pipeline_serializer_spec.rb
spec/serializers/pipeline_serializer_spec.rb
+1
-1
spec/support/prometheus/additional_metrics_shared_examples.rb
.../support/prometheus/additional_metrics_shared_examples.rb
+44
-0
No files found.
app/assets/stylesheets/pages/settings.scss
View file @
a8e34125
...
@@ -253,19 +253,29 @@
...
@@ -253,19 +253,29 @@
}
}
}
}
.loading-metrics
,
.custom-monitored-metrics
{
.empty-metrics
{
.panel-title
{
padding
:
30px
10px
;
display
:
flex
;
align-items
:
center
;
p
,
>
.btn-success
{
.btn
{
margin-left
:
auto
;
margin-top
:
10px
;
}
margin-bottom
:
0
;
}
.custom-metric
{
display
:
flex
;
align-items
:
center
;
}
.custom-metric-link-bold
{
font-weight
:
$gl-font-weight-bold
;
text-decoration
:
none
;
}
}
}
}
.loading-metrics
.metrics-load-spinner
{
.loading-metrics
.metrics-load-spinner
{
color
:
$
loading-color
;
color
:
$
gl-text-color-secondary
;
}
}
.metrics-list
{
.metrics-list
{
...
...
app/controllers/projects/prometheus/metrics_controller.rb
View file @
a8e34125
...
@@ -18,8 +18,85 @@ module Projects
...
@@ -18,8 +18,85 @@ module Projects
end
end
end
end
def
validate_query
respond_to
do
|
format
|
format
.
json
do
result
=
prometheus_adapter
.
query
(
:validate
,
params
[
:query
])
if
result
.
any?
render
json:
result
else
head
:no_content
end
end
end
end
def
new
@metric
=
project
.
prometheus_metrics
.
new
end
def
index
respond_to
do
|
format
|
format
.
json
do
metrics
=
project
.
prometheus_metrics
response
=
{}
if
metrics
.
any?
response
[
:metrics
]
=
PrometheusMetricSerializer
.
new
(
project:
project
)
.
represent
(
metrics
.
order
(
created_at: :asc
))
end
render
json:
response
end
end
end
def
create
@metric
=
project
.
prometheus_metrics
.
create
(
metrics_params
)
if
@metric
.
persisted?
redirect_to
edit_project_service_path
(
project
,
PrometheusService
),
notice:
'Metric was successfully added.'
else
render
'new'
end
end
def
update
@metric
=
project
.
prometheus_metrics
.
find
(
params
[
:id
])
@metric
.
update
(
metrics_params
)
if
@metric
.
persisted?
redirect_to
edit_project_service_path
(
project
,
PrometheusService
),
notice:
'Metric was successfully updated.'
else
render
'edit'
end
end
def
edit
@metric
=
project
.
prometheus_metrics
.
find
(
params
[
:id
])
end
def
destroy
metric
=
project
.
prometheus_metrics
.
find
(
params
[
:id
])
metric
.
destroy
respond_to
do
|
format
|
format
.
html
do
redirect_to
edit_project_service_path
(
project
,
PrometheusService
),
status:
303
end
format
.
json
do
head
:ok
end
end
end
private
private
def
metrics_params
params
.
require
(
:prometheus_metric
).
permit
(
:title
,
:query
,
:y_label
,
:unit
,
:legend
,
:group
)
end
def
prometheus_adapter
def
prometheus_adapter
@prometheus_adapter
||=
::
Prometheus
::
AdapterService
.
new
(
project
).
prometheus_adapter
@prometheus_adapter
||=
::
Prometheus
::
AdapterService
.
new
(
project
).
prometheus_adapter
end
end
...
...
app/models/concerns/prometheus_adapter.rb
View file @
a8e34125
...
@@ -26,7 +26,13 @@ module PrometheusAdapter
...
@@ -26,7 +26,13 @@ module PrometheusAdapter
query_class
=
Gitlab
::
Prometheus
::
Queries
.
const_get
(
"
#{
query_name
.
to_s
.
classify
}
Query"
)
query_class
=
Gitlab
::
Prometheus
::
Queries
.
const_get
(
"
#{
query_name
.
to_s
.
classify
}
Query"
)
args
.
map!
(
&
:id
)
args
.
map!
do
|
arg
|
if
arg
.
respond_to?
(
:id
)
arg
.
id
else
arg
end
end
with_reactive_cache
(
query_class
.
name
,
*
args
,
&
query_class
.
method
(
:transform_reactive_result
))
with_reactive_cache
(
query_class
.
name
,
*
args
,
&
query_class
.
method
(
:transform_reactive_result
))
end
end
...
...
app/models/project.rb
View file @
a8e34125
...
@@ -200,6 +200,8 @@ class Project < ActiveRecord::Base
...
@@ -200,6 +200,8 @@ class Project < ActiveRecord::Base
has_one
:cluster_project
,
class_name:
'Clusters::Project'
has_one
:cluster_project
,
class_name:
'Clusters::Project'
has_many
:clusters
,
through: :cluster_project
,
class_name:
'Clusters::Cluster'
has_many
:clusters
,
through: :cluster_project
,
class_name:
'Clusters::Cluster'
has_many
:prometheus_metrics
# Container repositories need to remove data from the container registry,
# Container repositories need to remove data from the container registry,
# which is not managed by the DB. Hence we're still using dependent: :destroy
# which is not managed by the DB. Hence we're still using dependent: :destroy
# here.
# here.
...
...
app/views/projects/services/prometheus/_show.html.haml
View file @
a8e34125
...
@@ -3,13 +3,37 @@
...
@@ -3,13 +3,37 @@
%h4
.prepend-top-0
%h4
.prepend-top-0
=
s_
(
'PrometheusService|Metrics'
)
=
s_
(
'PrometheusService|Metrics'
)
%p
%p
=
s_
(
'PrometheusService|
Metrics are automatically configured and
monitored based on a library of metrics from popular exporters.'
)
=
s_
(
'PrometheusService|
Common metrics are automatically
monitored based on a library of metrics from popular exporters.'
)
=
link_to
s_
(
'PrometheusService|More information'
),
help_page_path
(
'user/project/integrations/prometheus
'
)
=
link_to
s_
(
'PrometheusService|More information'
),
help_page_path
(
'user/project/integrations/prometheus
_library/metrics'
),
target:
'_blank'
,
rel:
"noopener noreferrer"
.col-lg-9
.col-lg-9
<
<<<<<<
HEAD
.panel.panel-default.js-panel-monitored-metrics
{
data:
{
active_metrics:
active_common_project_prometheus_metrics_path
(
@project
,
:json
),
metrics_help_path:
help_page_path
(
'user/project/integrations/prometheus_library/metrics'
)
}
}
.panel.panel-default.js-panel-monitored-metrics
{
data:
{
active_metrics:
active_common_project_prometheus_metrics_path
(
@project
,
:json
),
metrics_help_path:
help_page_path
(
'user/project/integrations/prometheus_library/metrics'
)
}
}
.panel-heading
.panel-heading
%h3
.panel-title
%h3
.panel-title
==
=====
.panel.panel-default.custom-monitored-metrics.js-panel-custom-monitored-metrics
{
data:
{
active_custom_metrics:
project_prometheus_metrics_path
(
@project
),
environments_data:
environments_list_data
}
}
.panel-heading
%h3
.panel-title
=
s_
(
'PrometheusService|Custom metrics'
)
%span
.badge.js-custom-monitored-count
0
=
link_to
s_
(
'PrometheusService|New metric'
),
new_project_prometheus_metric_path
(
@project
),
class:
'btn btn-success js-new-metric-button hidden'
.panel-body
.flash-container.hidden
.flash-warning
.flash-text
.loading-metrics.js-loading-custom-metrics
%p
.prepend-top-10.prepend-left-10
=
icon
(
'spinner spin'
,
class:
'metrics-load-spinner'
)
=
s_
(
'PrometheusService|Finding custom metrics...'
)
.empty-metrics.hidden.js-empty-custom-metrics
=
link_to
s_
(
'PrometheusService|New metric'
),
new_project_prometheus_metric_path
(
@project
),
class:
'btn btn-success prepend-top-10 prepend-left-10'
%ul
.list-unstyled.metrics-list.hidden.js-custom-metrics-list
.panel.panel-default.js-panel-monitored-metrics
{
data:
{
active_metrics:
active_common_project_prometheus_metrics_path
(
@project
,
:json
),
metrics_help_path:
help_page_path
(
'user/project/integrations/prometheus_library/metrics'
)
}
}
.panel-heading
%h3
.panel-title
>
>>>>>> master
=
s_
(
'PrometheusService|Common metrics'
)
=
s_
(
'PrometheusService|Common metrics'
)
%span
.badge.js-monitored-count
0
%span
.badge.js-monitored-count
0
.panel-body
.panel-body
...
...
app/workers/all_queues.yml
View file @
a8e34125
...
@@ -113,6 +113,7 @@
...
@@ -113,6 +113,7 @@
-
cronjob:geo_prune_event_log
-
cronjob:geo_prune_event_log
-
cronjob:geo_repository_sync
-
cronjob:geo_repository_sync
-
cronjob:geo_repository_verification_primary_batch
-
cronjob:geo_repository_verification_primary_batch
-
cronjob:geo_repository_verification_secondary_scheduler
-
cronjob:geo_sidekiq_cron_config
-
cronjob:geo_sidekiq_cron_config
-
cronjob:historical_data
-
cronjob:historical_data
-
cronjob:ldap_all_groups_sync
-
cronjob:ldap_all_groups_sync
...
@@ -133,6 +134,7 @@
...
@@ -133,6 +134,7 @@
-
geo:geo_repository_shard_sync
-
geo:geo_repository_shard_sync
-
geo:geo_repository_verification_primary_shard
-
geo:geo_repository_verification_primary_shard
-
geo:geo_repository_verification_primary_single
-
geo:geo_repository_verification_primary_single
-
geo:geo_repository_verification_secondary_single
-
object_storage_upload
-
object_storage_upload
-
object_storage:object_storage_background_move
-
object_storage:object_storage_background_move
...
...
config/initializers/1_settings.rb
View file @
a8e34125
...
@@ -479,6 +479,9 @@ Settings.cron_jobs['geo_prune_event_log_worker']['job_class'] ||= 'Geo::PruneEve
...
@@ -479,6 +479,9 @@ Settings.cron_jobs['geo_prune_event_log_worker']['job_class'] ||= 'Geo::PruneEve
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
]
||=
Settingslogic
.
new
({})
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
]
||=
Settingslogic
.
new
({})
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
][
'cron'
]
||=
'*/1 * * * *'
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
][
'cron'
]
||=
'*/1 * * * *'
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
][
'job_class'
]
||=
'Geo::RepositoryVerification::Primary::BatchWorker'
Settings
.
cron_jobs
[
'geo_repository_verification_primary_batch_worker'
][
'job_class'
]
||=
'Geo::RepositoryVerification::Primary::BatchWorker'
Settings
.
cron_jobs
[
'geo_repository_verification_secondary_scheduler_worker'
]
||=
Settingslogic
.
new
({})
Settings
.
cron_jobs
[
'geo_repository_verification_secondary_scheduler_worker'
][
'cron'
]
||=
'*/1 * * * *'
Settings
.
cron_jobs
[
'geo_repository_verification_secondary_scheduler_worker'
][
'job_class'
]
||=
'Geo::RepositoryVerification::Secondary::SchedulerWorker'
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
]
||=
Settingslogic
.
new
({})
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
]
||=
Settingslogic
.
new
({})
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
][
'cron'
]
||=
'0 * * * *'
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
][
'cron'
]
||=
'0 * * * *'
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
][
'job_class'
]
=
'ImportExportProjectCleanupWorker'
Settings
.
cron_jobs
[
'import_export_project_cleanup_worker'
][
'job_class'
]
=
'ImportExportProjectCleanupWorker'
...
...
config/routes/project.rb
View file @
a8e34125
...
@@ -78,7 +78,8 @@ constraints(ProjectUrlConstrainer.new) do
...
@@ -78,7 +78,8 @@ constraints(ProjectUrlConstrainer.new) do
resource
:mattermost
,
only:
[
:new
,
:create
]
resource
:mattermost
,
only:
[
:new
,
:create
]
namespace
:prometheus
do
namespace
:prometheus
do
resources
:metrics
,
constraints:
{
id:
%r{[^
\/
]+}
},
only:
[]
do
resources
:metrics
,
constraints:
{
id:
%r{[^
\/
]+}
},
only:
[
:index
,
:new
,
:create
,
:edit
,
:update
,
:destroy
]
do
post
:validate_query
,
on: :collection
get
:active_common
,
on: :collection
get
:active_common
,
on: :collection
end
end
end
end
...
...
db/schema.rb
View file @
a8e34125
...
@@ -1047,6 +1047,10 @@ ActiveRecord::Schema.define(version: 20180307164427) do
...
@@ -1047,6 +1047,10 @@ ActiveRecord::Schema.define(version: 20180307164427) do
t
.
integer
"job_artifacts_failed_count"
t
.
integer
"job_artifacts_failed_count"
t
.
string
"version"
t
.
string
"version"
t
.
string
"revision"
t
.
string
"revision"
t
.
integer
"repositories_verified_count"
t
.
integer
"repositories_verification_failed_count"
t
.
integer
"wikis_verified_count"
t
.
integer
"wikis_verification_failed_count"
end
end
add_index
"geo_node_statuses"
,
[
"geo_node_id"
],
name:
"index_geo_node_statuses_on_geo_node_id"
,
unique:
true
,
using: :btree
add_index
"geo_node_statuses"
,
[
"geo_node_id"
],
name:
"index_geo_node_statuses_on_geo_node_id"
,
unique:
true
,
using: :btree
...
@@ -1531,7 +1535,10 @@ ActiveRecord::Schema.define(version: 20180307164427) do
...
@@ -1531,7 +1535,10 @@ ActiveRecord::Schema.define(version: 20180307164427) do
t
.
string
"merge_jid"
t
.
string
"merge_jid"
t
.
boolean
"discussion_locked"
t
.
boolean
"discussion_locked"
t
.
integer
"latest_merge_request_diff_id"
t
.
integer
"latest_merge_request_diff_id"
<<<<<<<
HEAD
t
.
string
"rebase_commit_sha"
t
.
string
"rebase_commit_sha"
=======
>>>>>>>
master
t
.
boolean
"allow_maintainer_to_push"
t
.
boolean
"allow_maintainer_to_push"
end
end
...
@@ -2001,6 +2008,21 @@ ActiveRecord::Schema.define(version: 20180307164427) do
...
@@ -2001,6 +2008,21 @@ ActiveRecord::Schema.define(version: 20180307164427) do
add_index
"projects"
,
[
"star_count"
],
name:
"index_projects_on_star_count"
,
using: :btree
add_index
"projects"
,
[
"star_count"
],
name:
"index_projects_on_star_count"
,
using: :btree
add_index
"projects"
,
[
"visibility_level"
],
name:
"index_projects_on_visibility_level"
,
using: :btree
add_index
"projects"
,
[
"visibility_level"
],
name:
"index_projects_on_visibility_level"
,
using: :btree
create_table
"prometheus_metrics"
,
force: :cascade
do
|
t
|
t
.
integer
"project_id"
t
.
string
"title"
,
null:
false
t
.
string
"query"
,
null:
false
t
.
string
"y_label"
t
.
string
"unit"
t
.
string
"legend"
t
.
integer
"group"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
datetime
"updated_at"
,
null:
false
end
add_index
"prometheus_metrics"
,
[
"group"
],
name:
"index_prometheus_metrics_on_group"
,
using: :btree
add_index
"prometheus_metrics"
,
[
"project_id"
],
name:
"index_prometheus_metrics_on_project_id"
,
using: :btree
create_table
"protected_branch_merge_access_levels"
,
force: :cascade
do
|
t
|
create_table
"protected_branch_merge_access_levels"
,
force: :cascade
do
|
t
|
t
.
integer
"protected_branch_id"
,
null:
false
t
.
integer
"protected_branch_id"
,
null:
false
t
.
integer
"access_level"
,
default:
40
t
.
integer
"access_level"
,
default:
40
...
@@ -2701,6 +2723,7 @@ ActiveRecord::Schema.define(version: 20180307164427) do
...
@@ -2701,6 +2723,7 @@ ActiveRecord::Schema.define(version: 20180307164427) do
add_foreign_key
"project_mirror_data"
,
"projects"
,
name:
"fk_d1aad367d7"
,
on_delete: :cascade
add_foreign_key
"project_mirror_data"
,
"projects"
,
name:
"fk_d1aad367d7"
,
on_delete: :cascade
add_foreign_key
"project_repository_states"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"project_repository_states"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"project_statistics"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"project_statistics"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"prometheus_metrics"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"protected_branch_merge_access_levels"
,
"namespaces"
,
column:
"group_id"
,
name:
"fk_98f3d044fe"
,
on_delete: :cascade
add_foreign_key
"protected_branch_merge_access_levels"
,
"namespaces"
,
column:
"group_id"
,
name:
"fk_98f3d044fe"
,
on_delete: :cascade
add_foreign_key
"protected_branch_merge_access_levels"
,
"protected_branches"
,
name:
"fk_8a3072ccb3"
,
on_delete: :cascade
add_foreign_key
"protected_branch_merge_access_levels"
,
"protected_branches"
,
name:
"fk_8a3072ccb3"
,
on_delete: :cascade
add_foreign_key
"protected_branch_merge_access_levels"
,
"users"
add_foreign_key
"protected_branch_merge_access_levels"
,
"users"
...
...
ee/app/assets/javascripts/geo_nodes/components/geo_node_details.vue
View file @
a8e34125
...
@@ -203,6 +203,22 @@
...
@@ -203,6 +203,22 @@
</li>
</li>
<
template
v-if=
"showAdvanceItems"
>
<
template
v-if=
"showAdvanceItems"
>
<template
v-if=
"node.primary"
>
<template
v-if=
"node.primary"
>
<geo-node-detail-item
:item-title=
"s__('GeoNodes|Repositories checksummed:')"
:success-label=
"s__('GeoNodes|Checksummed')"
:neutral-label=
"s__('GeoNodes|Not checksummed')"
:failure-label=
"s__('GeoNodes|Failed')"
:item-value=
"nodeDetails.verifiedRepositories"
:item-value-type=
"valueType.GRAPH"
/>
<geo-node-detail-item
:item-title=
"s__('GeoNodes|Wikis checksummed:')"
:success-label=
"s__('GeoNodes|Checksummed')"
:neutral-label=
"s__('GeoNodes|Not checksummed')"
:failure-label=
"s__('GeoNodes|Failed')"
:item-value=
"nodeDetails.verifiedWikis"
:item-value-type=
"valueType.GRAPH"
/>
<geo-node-detail-item
<geo-node-detail-item
:item-title=
"s__('GeoNodes|Replication slots:')"
:item-title=
"s__('GeoNodes|Replication slots:')"
:success-label=
"s__('GeoNodes|Used slots')"
:success-label=
"s__('GeoNodes|Used slots')"
...
@@ -219,6 +235,22 @@
...
@@ -219,6 +235,22 @@
/>
/>
</
template
>
</
template
>
<
template
v-else
>
<
template
v-else
>
<geo-node-detail-item
:item-title=
"s__('GeoNodes|Repository checksums verified:')"
:success-label=
"s__('GeoNodes|Verified')"
:neutral-label=
"s__('GeoNodes|Unverified')"
:failure-label=
"s__('GeoNodes|Failed')"
:item-value=
"nodeDetails.verifiedRepositories"
:item-value-type=
"valueType.GRAPH"
/>
<geo-node-detail-item
:item-title=
"s__('GeoNodes|Wiki checksums verified:')"
:success-label=
"s__('GeoNodes|Verified')"
:neutral-label=
"s__('GeoNodes|Unverified')"
:failure-label=
"s__('GeoNodes|Failed')"
:item-value=
"nodeDetails.verifiedWikis"
:item-value-type=
"valueType.GRAPH"
/>
<geo-node-detail-item
<geo-node-detail-item
css-class=
"node-detail-value-bold"
css-class=
"node-detail-value-bold"
:item-title=
"s__('GeoNodes|Database replication lag:')"
:item-title=
"s__('GeoNodes|Database replication lag:')"
...
...
ee/app/assets/javascripts/geo_nodes/store/geo_nodes_store.js
View file @
a8e34125
...
@@ -87,6 +87,16 @@ export default class GeoNodesStore {
...
@@ -87,6 +87,16 @@ export default class GeoNodesStore {
successCount
:
rawNodeDetails
.
wikis_synced_count
||
0
,
successCount
:
rawNodeDetails
.
wikis_synced_count
||
0
,
failureCount
:
rawNodeDetails
.
wikis_failed_count
||
0
,
failureCount
:
rawNodeDetails
.
wikis_failed_count
||
0
,
},
},
verifiedRepositories
:
{
totalCount
:
rawNodeDetails
.
repositories_count
||
0
,
successCount
:
rawNodeDetails
.
repositories_verified_count
||
0
,
failureCount
:
rawNodeDetails
.
repositories_verification_failed_count
||
0
,
},
verifiedWikis
:
{
totalCount
:
rawNodeDetails
.
wikis_count
||
0
,
successCount
:
rawNodeDetails
.
wikis_verified_count
||
0
,
failureCount
:
rawNodeDetails
.
wikis_verification_failed_count
||
0
,
},
lfs
:
{
lfs
:
{
totalCount
:
rawNodeDetails
.
lfs_objects_count
||
0
,
totalCount
:
rawNodeDetails
.
lfs_objects_count
||
0
,
successCount
:
rawNodeDetails
.
lfs_objects_synced_count
||
0
,
successCount
:
rawNodeDetails
.
lfs_objects_synced_count
||
0
,
...
...
ee/app/assets/javascripts/pages/projects/services/edit/index.js
0 → 100644
View file @
a8e34125
import
IntegrationSettingsForm
from
'
~/integrations/integration_settings_form
'
;
import
PrometheusMetrics
from
'
ee/prometheus_metrics/prometheus_metrics
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
const
integrationSettingsForm
=
new
IntegrationSettingsForm
(
'
.js-integration-settings-form
'
);
integrationSettingsForm
.
init
();
const
prometheusSettingsWrapper
=
document
.
querySelector
(
'
.js-prometheus-metrics-monitoring
'
);
if
(
prometheusSettingsWrapper
)
{
const
prometheusMetrics
=
new
PrometheusMetrics
(
'
.js-prometheus-metrics-monitoring
'
);
prometheusMetrics
.
loadActiveCustomMetrics
();
}
});
ee/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
0 → 100644
View file @
a8e34125
import
_
from
'
underscore
'
;
import
PrometheusMetrics
from
'
~/prometheus_metrics/prometheus_metrics
'
;
import
PANEL_STATE
from
'
~/prometheus_metrics/constants
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
capitalizeFirstCharacter
}
from
'
~/lib/utils/text_utility
'
;
export
default
class
EEPrometheusMetrics
extends
PrometheusMetrics
{
constructor
(
wrapperSelector
)
{
super
(
wrapperSelector
);
this
.
$wrapperCustomMetrics
=
$
(
wrapperSelector
);
this
.
$monitoredCustomMetricsPanel
=
this
.
$wrapperCustomMetrics
.
find
(
'
.js-panel-custom-monitored-metrics
'
);
this
.
$monitoredCustomMetricsCount
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-custom-monitored-count
'
);
this
.
$monitoredCustomMetricsLoading
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-loading-custom-metrics
'
);
this
.
$monitoredCustomMetricsEmpty
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-empty-custom-metrics
'
);
this
.
$monitoredCustomMetricsList
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-custom-metrics-list
'
);
this
.
$newCustomMetricButton
=
this
.
$monitoredCustomMetricsPanel
.
find
(
'
.js-new-metric-button
'
);
this
.
$flashCustomMetricsContainer
=
this
.
$wrapperCustomMetrics
.
find
(
'
.flash-container
'
);
this
.
customMetrics
=
[];
this
.
environmentsData
=
[];
this
.
activeCustomMetricsEndpoint
=
this
.
$monitoredCustomMetricsPanel
.
data
(
'
active-custom-metrics
'
);
this
.
environmentsDataEndpoint
=
this
.
$monitoredCustomMetricsPanel
.
data
(
'
environments-data-endpoint
'
);
}
showMonitoringCustomMetricsPanelState
(
stateName
)
{
switch
(
stateName
)
{
case
PANEL_STATE
.
LOADING
:
this
.
$monitoredCustomMetricsLoading
.
removeClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsEmpty
.
addClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsList
.
addClass
(
'
hidden
'
);
this
.
$newCustomMetricButton
.
addClass
(
'
hidden
'
);
break
;
case
PANEL_STATE
.
LIST
:
this
.
$monitoredCustomMetricsLoading
.
addClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsEmpty
.
addClass
(
'
hidden
'
);
this
.
$newCustomMetricButton
.
removeClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsList
.
removeClass
(
'
hidden
'
);
break
;
default
:
this
.
$monitoredCustomMetricsLoading
.
addClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsEmpty
.
removeClass
(
'
hidden
'
);
this
.
$monitoredCustomMetricsList
.
addClass
(
'
hidden
'
);
this
.
$newCustomMetricButton
.
addClass
(
'
hidden
'
);
break
;
}
}
populateCustomMetrics
()
{
const
sortedMetrics
=
_
(
this
.
customMetrics
).
chain
()
.
map
(
metric
=>
({
...
metric
,
group
:
capitalizeFirstCharacter
(
metric
.
group
)
}))
.
sortBy
(
'
title
'
)
.
sortBy
(
'
group
'
)
.
value
();
sortedMetrics
.
forEach
((
metric
)
=>
{
this
.
$monitoredCustomMetricsList
.
append
(
EEPrometheusMetrics
.
customMetricTemplate
(
metric
));
});
this
.
$monitoredCustomMetricsCount
.
text
(
this
.
customMetrics
.
length
);
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
LIST
);
if
(
!
this
.
environmentsData
)
{
this
.
showFlashMessage
(
s__
(
'
PrometheusService|These metrics will only be monitored after your first deployment to an environment
'
));
}
}
showFlashMessage
(
message
)
{
this
.
$flashCustomMetricsContainer
.
removeClass
(
'
hidden
'
);
this
.
$flashCustomMetricsContainer
.
find
(
'
.flash-text
'
).
text
(
message
);
}
loadActiveCustomMetrics
()
{
super
.
loadActiveMetrics
();
Promise
.
all
([
axios
.
get
(
this
.
activeCustomMetricsEndpoint
),
axios
.
get
(
this
.
environmentsDataEndpoint
),
])
.
then
(([
customMetrics
,
environmentsData
])
=>
{
this
.
environmentsData
=
environmentsData
.
data
.
environments
;
if
(
!
customMetrics
.
data
||
!
customMetrics
.
data
.
metrics
)
{
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
}
else
{
this
.
customMetrics
=
customMetrics
.
data
.
metrics
;
this
.
populateCustomMetrics
(
customMetrics
.
data
.
metrics
);
}
})
.
catch
((
customMetricError
)
=>
{
this
.
showFlashMessage
(
customMetricError
);
this
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
});
}
static
customMetricTemplate
(
metric
)
{
return
`
<li class="custom-metric">
<a href="
${
_
.
escape
(
metric
.
edit_path
)}
" class="custom-metric-link-bold">
${
_
.
escape
(
metric
.
group
)}
/
${
_
.
escape
(
metric
.
title
)}
(
${
_
.
escape
(
metric
.
unit
)}
)
</a>
</li>
`
;
}
}
ee/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
View file @
a8e34125
...
@@ -377,6 +377,8 @@ export default {
...
@@ -377,6 +377,8 @@ export default {
v-if="shouldRenderRelatedLinks"
v-if="shouldRenderRelatedLinks"
:related-links="mr.relatedLinks"
:related-links="mr.relatedLinks"
/>
/>
<mr-widget-maintainer-edit
:maintainerEditAllowed="mr.maintainerEditAllowed" />
</div>
</div>
<div class="mr-widget-footer" v-if="shouldRenderMergeHelp">
<div class="mr-widget-footer" v-if="shouldRenderMergeHelp">
<mr-widget-merge-help />
<mr-widget-merge-help />
...
...
ee/app/controllers/ee/admin/logs_controller.rb
View file @
a8e34125
...
@@ -6,7 +6,8 @@ module EE::Admin::LogsController
...
@@ -6,7 +6,8 @@ module EE::Admin::LogsController
def
loggers
def
loggers
strong_memoize
(
:loggers
)
do
strong_memoize
(
:loggers
)
do
super
+
[
super
+
[
Gitlab
::
GeoLogger
Gitlab
::
GeoLogger
,
Gitlab
::
Geo
::
RepositoryVerificationLogger
]
]
end
end
end
end
...
...
ee/app/finders/geo/project_registry_finder.rb
View file @
a8e34125
...
@@ -39,14 +39,58 @@ module Geo
...
@@ -39,14 +39,58 @@ module Geo
end
end
def
find_failed_project_registries
(
type
=
nil
)
def
find_failed_project_registries
(
type
=
nil
)
relation
=
if
selective_sync?
if
selective_sync?
legacy_find_filtered_failed_projects
(
type
)
legacy_find_filtered_failed_projects
(
type
)
else
else
find_filtered_failed_project_registries
(
type
)
find_filtered_failed_project_registries
(
type
)
end
end
end
def
count_verified_repositories
relation
=
if
use_legacy_queries?
legacy_find_verified_repositories
else
find_verified_repositories
end
relation
.
count
end
def
count_verified_wikis
relation
=
if
use_legacy_queries?
legacy_find_verified_wikis
else
find_verified_wikis
end
relation
.
count
end
def
count_verification_failed_repositories
find_verification_failed_project_registries
(
'repository'
).
count
end
def
count_verification_failed_wikis
find_verification_failed_project_registries
(
'wiki'
).
count
end
relation
def
find_verification_failed_project_registries
(
type
=
nil
)
if
use_legacy_queries?
legacy_find_filtered_verification_failed_projects
(
type
)
else
find_filtered_verification_failed_project_registries
(
type
)
end
end
# find all registries that need a repository or wiki verified
def
find_registries_to_verify
if
use_legacy_queries?
legacy_find_registries_to_verify
else
fdw_find_registries_to_verify
end
end
end
def
find_unsynced_projects
(
batch_size
:)
def
find_unsynced_projects
(
batch_size
:)
...
@@ -77,6 +121,14 @@ module Geo
...
@@ -77,6 +121,14 @@ module Geo
Geo
::
ProjectRegistry
.
synced_repos
Geo
::
ProjectRegistry
.
synced_repos
end
end
def
find_verified_repositories
Geo
::
ProjectRegistry
.
verified_repos
end
def
find_verified_wikis
Geo
::
ProjectRegistry
.
verified_wikis
end
def
find_filtered_failed_project_registries
(
type
=
nil
)
def
find_filtered_failed_project_registries
(
type
=
nil
)
case
type
case
type
when
'repository'
when
'repository'
...
@@ -88,17 +140,52 @@ module Geo
...
@@ -88,17 +140,52 @@ module Geo
end
end
end
end
def
find_filtered_verification_failed_project_registries
(
type
=
nil
)
case
type
when
'repository'
Geo
::
ProjectRegistry
.
verification_failed_repos
when
'wiki'
Geo
::
ProjectRegistry
.
verification_failed_wikis
else
Geo
::
ProjectRegistry
.
verification_failed
end
end
def
conditions_for_verification
(
type
,
use_fdw
=
true
)
last_verification_failed
=
"last_
#{
type
}
_verification_failed"
.
to_sym
verification_checksum
=
"
#{
type
}
_verification_checksum"
.
to_sym
last_verification_at
=
"last_
#{
type
}
_verification_at"
.
to_sym
state_arel
=
use_fdw
?
fdw_repository_state_arel
:
legacy_repository_state_arel
# primary verification did not fail
primary_verification_not_failed
=
state_arel
[
last_verification_failed
].
eq
(
false
)
# primary checksum is not NULL
primary_has_checksum
=
state_arel
[
verification_checksum
].
not_eq
(
nil
)
# primary was verified later than the secondary verification
primary_recently_verified
=
state_arel
[
last_verification_at
].
gt
(
registry_arel
[
last_verification_at
])
.
or
(
registry_arel
[
last_verification_at
].
eq
(
nil
))
# secondary verification failed and the last verification was over 24.hours.ago
# this allows us to retry any verification failures if they haven't already corrected themselves
secondary_failure_period
=
registry_arel
[
last_verification_at
].
lt
(
24
.
hours
.
ago
)
.
and
(
registry_arel
[
last_verification_failed
].
eq
(
true
))
primary_verification_not_failed
.
and
(
primary_has_checksum
)
.
and
(
primary_recently_verified
)
.
or
(
secondary_failure_period
)
end
#
#
# FDW accessors
# FDW accessors
#
#
def
fdw_table
Geo
::
Fdw
::
Project
.
table_name
end
# @return [ActiveRecord::Relation<Geo::Fdw::Project>]
# @return [ActiveRecord::Relation<Geo::Fdw::Project>]
def
fdw_find_unsynced_projects
def
fdw_find_unsynced_projects
Geo
::
Fdw
::
Project
.
joins
(
"LEFT OUTER JOIN project_registry ON project_registry.project_id =
#{
fdw_table
}
.id"
)
Geo
::
Fdw
::
Project
.
joins
(
"LEFT OUTER JOIN project_registry ON project_registry.project_id =
#{
fdw_
project_
table
}
.id"
)
.
where
(
project_registry:
{
project_id:
nil
})
.
where
(
project_registry:
{
project_id:
nil
})
end
end
...
@@ -121,11 +208,19 @@ module Geo
...
@@ -121,11 +208,19 @@ module Geo
# @return [ActiveRecord::Relation<Geo::Fdw::Project>]
# @return [ActiveRecord::Relation<Geo::Fdw::Project>]
def
fdw_find_projects_updated_recently
def
fdw_find_projects_updated_recently
Geo
::
Fdw
::
Project
.
joins
(
"INNER JOIN project_registry ON project_registry.project_id =
#{
fdw_table
}
.id"
)
Geo
::
Fdw
::
Project
.
joins
(
"INNER JOIN project_registry ON project_registry.project_id =
#{
fdw_
project_
table
}
.id"
)
.
merge
(
Geo
::
ProjectRegistry
.
dirty
)
.
merge
(
Geo
::
ProjectRegistry
.
dirty
)
.
merge
(
Geo
::
ProjectRegistry
.
retry_due
)
.
merge
(
Geo
::
ProjectRegistry
.
retry_due
)
end
end
# find all registries that need a repository or wiki verified
# @return [ActiveRecord::Relation<Geo::ProjectRegistry>] list of registries that need verification
def
fdw_find_registries_to_verify
Geo
::
ProjectRegistry
.
joins
(
"LEFT OUTER JOIN
#{
fdw_repository_state_table
}
ON
#{
fdw_repository_state_table
}
.project_id = project_registry.project_id"
)
.
where
(
conditions_for_verification
(
:repository
,
true
).
or
(
conditions_for_verification
(
:wiki
,
true
)))
end
#
#
# Legacy accessors (non FDW)
# Legacy accessors (non FDW)
#
#
...
@@ -176,6 +271,16 @@ module Geo
...
@@ -176,6 +271,16 @@ module Geo
)
)
end
end
# @return [ActiveRecord::Relation<Geo::ProjectRegistry>] list of verified projects
def
legacy_find_verified_repositories
legacy_find_project_registries
(
Geo
::
ProjectRegistry
.
verified_repos
)
end
# @return [ActiveRecord::Relation<Geo::ProjectRegistry>] list of verified projects
def
legacy_find_verified_wikis
legacy_find_project_registries
(
Geo
::
ProjectRegistry
.
verified_wikis
)
end
# @return [ActiveRecord::Relation<Project>] list of synced projects
# @return [ActiveRecord::Relation<Project>] list of synced projects
def
legacy_find_project_registries
(
project_registries
)
def
legacy_find_project_registries
(
project_registries
)
legacy_inner_join_registry_ids
(
legacy_inner_join_registry_ids
(
...
@@ -194,5 +299,65 @@ module Geo
...
@@ -194,5 +299,65 @@ module Geo
foreign_key: :project_id
foreign_key: :project_id
)
)
end
end
# @return [ActiveRecord::Relation<Project>] list of projects that verification has failed
def
legacy_find_filtered_verification_failed_projects
(
type
=
nil
)
legacy_inner_join_registry_ids
(
find_filtered_verification_failed_project_registries
(
type
),
current_node
.
projects
.
pluck
(
:id
),
Geo
::
ProjectRegistry
,
foreign_key: :project_id
)
end
# @return [ActiveRecord::Relation<Geo::ProjectRegistry>] list of registries that need verification
def
legacy_find_registries_to_verify
registries
=
Geo
::
ProjectRegistry
.
pluck
(
:project_id
,
:last_repository_verification_at
,
:last_wiki_verification_at
,
:last_repository_verification_failed
,
:last_wiki_verification_failed
)
return
Geo
::
ProjectRegistry
.
none
if
registries
.
empty?
id_and_values
=
registries
.
map
do
|
project_id
,
repo_at
,
wiki_at
,
repo_failed
,
wiki_failed
|
"(
#{
project_id
}
, to_timestamp(
#{
repo_at
.
to_i
}
), to_timestamp(
#{
wiki_at
.
to_i
}
),
#{
quote_value
(
repo_failed
)
}
,
#{
quote_value
(
wiki_failed
)
}
)"
end
joined_relation
=
ProjectRepositoryState
.
joins
(
<<~
SQL
)
INNER JOIN
(VALUES
#{
id_and_values
.
join
(
','
)
}
)
project_registry(project_id, last_repository_verification_at, last_wiki_verification_at,
last_repository_verification_failed, last_wiki_verification_failed)
ON
#{
ProjectRepositoryState
.
table_name
}
.project_id = project_registry.project_id
SQL
project_ids
=
joined_relation
.
where
(
conditions_for_verification
(
:repository
,
false
).
or
(
conditions_for_verification
(
:wiki
,
false
)))
.
pluck
(
:project_id
)
::
Geo
::
ProjectRegistry
.
where
(
project_id:
project_ids
)
end
private
def
registry_arel
Geo
::
ProjectRegistry
.
arel_table
end
def
fdw_repository_state_arel
Geo
::
Fdw
::
ProjectRepositoryState
.
arel_table
end
def
legacy_repository_state_arel
::
ProjectRepositoryState
.
arel_table
end
def
fdw_project_table
Geo
::
Fdw
::
Project
.
table_name
end
def
fdw_repository_state_table
Geo
::
Fdw
::
ProjectRepositoryState
.
table_name
end
end
end
end
end
ee/app/finders/geo/repository_verification_finder.rb
View file @
a8e34125
...
@@ -19,6 +19,22 @@ module Geo
...
@@ -19,6 +19,22 @@ module Geo
.
limit
(
batch_size
)
.
limit
(
batch_size
)
end
end
def
count_verified_repositories
Project
.
verified_repos
.
count
end
def
count_verified_wikis
Project
.
verified_wikis
.
count
end
def
count_verification_failed_repositories
Project
.
verification_failed_repos
.
count
end
def
count_verification_failed_wikis
Project
.
verification_failed_wikis
.
count
end
protected
protected
def
projects_table
def
projects_table
...
...
ee/app/models/ee/project.rb
View file @
a8e34125
...
@@ -56,6 +56,11 @@ module EE
...
@@ -56,6 +56,11 @@ module EE
scope
:with_remote_mirrors
,
->
{
joins
(
:remote_mirrors
).
where
(
remote_mirrors:
{
enabled:
true
}).
distinct
}
scope
:with_remote_mirrors
,
->
{
joins
(
:remote_mirrors
).
where
(
remote_mirrors:
{
enabled:
true
}).
distinct
}
scope
:with_wiki_enabled
,
->
{
with_feature_enabled
(
:wiki
)
}
scope
:with_wiki_enabled
,
->
{
with_feature_enabled
(
:wiki
)
}
scope
:verified_repos
,
->
{
joins
(
:repository_state
).
merge
(
ProjectRepositoryState
.
verified_repos
)
}
scope
:verified_wikis
,
->
{
joins
(
:repository_state
).
merge
(
ProjectRepositoryState
.
verified_wikis
)
}
scope
:verification_failed_repos
,
->
{
joins
(
:repository_state
).
merge
(
ProjectRepositoryState
.
verification_failed_repos
)
}
scope
:verification_failed_wikis
,
->
{
joins
(
:repository_state
).
merge
(
ProjectRepositoryState
.
verification_failed_wikis
)
}
delegate
:shared_runners_minutes
,
:shared_runners_seconds
,
:shared_runners_seconds_last_reset
,
delegate
:shared_runners_minutes
,
:shared_runners_seconds
,
:shared_runners_seconds_last_reset
,
to: :statistics
,
allow_nil:
true
to: :statistics
,
allow_nil:
true
...
...
ee/app/models/geo/fdw/project_repository_state.rb
0 → 100644
View file @
a8e34125
module
Geo
module
Fdw
class
ProjectRepositoryState
<
::
Geo
::
BaseFdw
self
.
table_name
=
Gitlab
::
Geo
::
Fdw
.
table
(
'project_repository_states'
)
end
end
end
ee/app/models/geo/project_registry.rb
View file @
a8e34125
class
Geo::ProjectRegistry
<
Geo
::
BaseRegistry
class
Geo::ProjectRegistry
<
Geo
::
BaseRegistry
include
::
EachBatch
belongs_to
:project
belongs_to
:project
validates
:project
,
presence:
true
,
uniqueness:
true
validates
:project
,
presence:
true
,
uniqueness:
true
...
@@ -6,6 +8,8 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
...
@@ -6,6 +8,8 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
scope
:dirty
,
->
{
where
(
arel_table
[
:resync_repository
].
eq
(
true
).
or
(
arel_table
[
:resync_wiki
].
eq
(
true
)))
}
scope
:dirty
,
->
{
where
(
arel_table
[
:resync_repository
].
eq
(
true
).
or
(
arel_table
[
:resync_wiki
].
eq
(
true
)))
}
scope
:failed_repos
,
->
{
where
(
arel_table
[
:repository_retry_count
].
gt
(
0
))
}
scope
:failed_repos
,
->
{
where
(
arel_table
[
:repository_retry_count
].
gt
(
0
))
}
scope
:failed_wikis
,
->
{
where
(
arel_table
[
:wiki_retry_count
].
gt
(
0
))
}
scope
:failed_wikis
,
->
{
where
(
arel_table
[
:wiki_retry_count
].
gt
(
0
))
}
scope
:verification_failed_repos
,
->
{
where
(
arel_table
[
:last_repository_verification_failed
].
eq
(
true
))
}
scope
:verification_failed_wikis
,
->
{
where
(
arel_table
[
:last_wiki_verification_failed
].
eq
(
true
))
}
def
self
.
failed
def
self
.
failed
repository_sync_failed
=
arel_table
[
:repository_retry_count
].
gt
(
0
)
repository_sync_failed
=
arel_table
[
:repository_retry_count
].
gt
(
0
)
...
@@ -14,6 +18,13 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
...
@@ -14,6 +18,13 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
where
(
repository_sync_failed
.
or
(
wiki_sync_failed
))
where
(
repository_sync_failed
.
or
(
wiki_sync_failed
))
end
end
def
self
.
verification_failed
repository_verification_failed
=
arel_table
[
:last_repository_verification_failed
].
eq
(
true
)
wiki_verification_failed
=
arel_table
[
:last_wiki_verification_failed
].
eq
(
true
)
where
(
repository_verification_failed
.
or
(
wiki_verification_failed
))
end
def
self
.
retry_due
def
self
.
retry_due
where
(
where
(
arel_table
[
:repository_retry_at
].
lt
(
Time
.
now
)
arel_table
[
:repository_retry_at
].
lt
(
Time
.
now
)
...
@@ -33,6 +44,16 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
...
@@ -33,6 +44,16 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
.
where
(
resync_wiki:
false
)
.
where
(
resync_wiki:
false
)
end
end
def
self
.
verified_repos
where
.
not
(
last_repository_verification_at:
nil
,
repository_verification_checksum:
nil
)
.
where
(
last_repository_verification_failed:
false
)
end
def
self
.
verified_wikis
where
.
not
(
last_wiki_verification_at:
nil
,
wiki_verification_checksum:
nil
)
.
where
(
last_wiki_verification_failed:
false
)
end
def
repository_sync_due?
(
scheduled_time
)
def
repository_sync_due?
(
scheduled_time
)
never_synced_repository?
||
repository_sync_needed?
(
scheduled_time
)
never_synced_repository?
||
repository_sync_needed?
(
scheduled_time
)
end
end
...
@@ -41,6 +62,22 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
...
@@ -41,6 +62,22 @@ class Geo::ProjectRegistry < Geo::BaseRegistry
project
.
wiki_enabled?
&&
(
never_synced_wiki?
||
wiki_sync_needed?
(
scheduled_time
))
project
.
wiki_enabled?
&&
(
never_synced_wiki?
||
wiki_sync_needed?
(
scheduled_time
))
end
end
delegate
:repository_state
,
to: :project
delegate
:repository_verification_checksum
,
:last_repository_verification_at
,
:wiki_verification_checksum
,
:last_wiki_verification_at
,
to: :repository_state
,
allow_nil:
true
,
prefix: :project
def
repository_path
(
type
)
repo_path
=
project
.
disk_path
case
type
when
:repository
repo_path
when
:wiki
"
#{
repo_path
}
.wiki"
end
end
private
private
def
never_synced_repository?
def
never_synced_repository?
...
...
ee/app/models/geo_node_status.rb
View file @
a8e34125
...
@@ -24,6 +24,10 @@ class GeoNodeStatus < ActiveRecord::Base
...
@@ -24,6 +24,10 @@ class GeoNodeStatus < ActiveRecord::Base
wikis_count:
'Total number of wikis available on primary'
,
wikis_count:
'Total number of wikis available on primary'
,
wikis_synced_count:
'Number of wikis synced on secondary'
,
wikis_synced_count:
'Number of wikis synced on secondary'
,
wikis_failed_count:
'Number of wikis failed to sync on secondary'
,
wikis_failed_count:
'Number of wikis failed to sync on secondary'
,
repositories_verified_count:
'Number of repositories verified on secondary'
,
repositories_verification_failed_count:
'Number of repositories failed to verify on secondary'
,
wikis_verified_count:
'Number of wikis verified on secondary'
,
wikis_verification_failed_count:
'Number of wikis failed to verify on secondary'
,
lfs_objects_count:
'Total number of local LFS objects available on primary'
,
lfs_objects_count:
'Total number of local LFS objects available on primary'
,
lfs_objects_synced_count:
'Number of local LFS objects synced on secondary'
,
lfs_objects_synced_count:
'Number of local LFS objects synced on secondary'
,
lfs_objects_failed_count:
'Number of local LFS objects failed to sync on secondary'
,
lfs_objects_failed_count:
'Number of local LFS objects failed to sync on secondary'
,
...
@@ -136,6 +140,10 @@ class GeoNodeStatus < ActiveRecord::Base
...
@@ -136,6 +140,10 @@ class GeoNodeStatus < ActiveRecord::Base
self
.
replication_slots_count
=
geo_node
.
replication_slots_count
self
.
replication_slots_count
=
geo_node
.
replication_slots_count
self
.
replication_slots_used_count
=
geo_node
.
replication_slots_used_count
self
.
replication_slots_used_count
=
geo_node
.
replication_slots_used_count
self
.
replication_slots_max_retained_wal_bytes
=
geo_node
.
replication_slots_max_retained_wal_bytes
self
.
replication_slots_max_retained_wal_bytes
=
geo_node
.
replication_slots_max_retained_wal_bytes
self
.
repositories_verified_count
=
repository_verification_finder
.
count_verified_repositories
self
.
repositories_verification_failed_count
=
repository_verification_finder
.
count_verification_failed_repositories
self
.
wikis_verified_count
=
repository_verification_finder
.
count_verified_wikis
self
.
wikis_verification_failed_count
=
repository_verification_finder
.
count_verification_failed_wikis
end
end
end
end
...
@@ -148,6 +156,10 @@ class GeoNodeStatus < ActiveRecord::Base
...
@@ -148,6 +156,10 @@ class GeoNodeStatus < ActiveRecord::Base
self
.
repositories_failed_count
=
projects_finder
.
count_failed_repositories
self
.
repositories_failed_count
=
projects_finder
.
count_failed_repositories
self
.
wikis_synced_count
=
projects_finder
.
count_synced_wikis
self
.
wikis_synced_count
=
projects_finder
.
count_synced_wikis
self
.
wikis_failed_count
=
projects_finder
.
count_failed_wikis
self
.
wikis_failed_count
=
projects_finder
.
count_failed_wikis
self
.
repositories_verified_count
=
projects_finder
.
count_verified_repositories
self
.
repositories_verification_failed_count
=
projects_finder
.
count_verification_failed_repositories
self
.
wikis_verified_count
=
projects_finder
.
count_verified_wikis
self
.
wikis_verification_failed_count
=
projects_finder
.
count_verification_failed_wikis
self
.
lfs_objects_synced_count
=
lfs_objects_finder
.
count_synced_lfs_objects
self
.
lfs_objects_synced_count
=
lfs_objects_finder
.
count_synced_lfs_objects
self
.
lfs_objects_failed_count
=
lfs_objects_finder
.
count_failed_lfs_objects
self
.
lfs_objects_failed_count
=
lfs_objects_finder
.
count_failed_lfs_objects
self
.
job_artifacts_synced_count
=
job_artifacts_finder
.
count_synced_job_artifacts
self
.
job_artifacts_synced_count
=
job_artifacts_finder
.
count_synced_job_artifacts
...
@@ -199,6 +211,14 @@ class GeoNodeStatus < ActiveRecord::Base
...
@@ -199,6 +211,14 @@ class GeoNodeStatus < ActiveRecord::Base
calc_percentage
(
wikis_count
,
wikis_synced_count
)
calc_percentage
(
wikis_count
,
wikis_synced_count
)
end
end
def
repositories_verified_in_percentage
calc_percentage
(
repositories_count
,
repositories_verified_count
)
end
def
wikis_verified_in_percentage
calc_percentage
(
wikis_count
,
wikis_verified_count
)
end
def
lfs_objects_synced_in_percentage
def
lfs_objects_synced_in_percentage
calc_percentage
(
lfs_objects_count
,
lfs_objects_synced_count
)
calc_percentage
(
lfs_objects_count
,
lfs_objects_synced_count
)
end
end
...
@@ -277,6 +297,10 @@ class GeoNodeStatus < ActiveRecord::Base
...
@@ -277,6 +297,10 @@ class GeoNodeStatus < ActiveRecord::Base
@projects_finder
||=
Geo
::
ProjectRegistryFinder
.
new
(
current_node:
geo_node
)
@projects_finder
||=
Geo
::
ProjectRegistryFinder
.
new
(
current_node:
geo_node
)
end
end
def
repository_verification_finder
@repository_verification_finder
||=
Geo
::
RepositoryVerificationFinder
.
new
end
def
calc_percentage
(
total
,
count
)
def
calc_percentage
(
total
,
count
)
return
0
if
!
total
.
present?
||
total
.
zero?
return
0
if
!
total
.
present?
||
total
.
zero?
...
...
ee/app/models/project_repository_state.rb
View file @
a8e34125
...
@@ -8,6 +8,9 @@ class ProjectRepositoryState < ActiveRecord::Base
...
@@ -8,6 +8,9 @@ class ProjectRepositoryState < ActiveRecord::Base
validates
:project
,
presence:
true
,
uniqueness:
true
validates
:project
,
presence:
true
,
uniqueness:
true
scope
:verification_failed_repos
,
->
{
where
(
arel_table
[
:last_repository_verification_failed
].
eq
(
true
))
}
scope
:verification_failed_wikis
,
->
{
where
(
arel_table
[
:last_wiki_verification_failed
].
eq
(
true
))
}
def
repository_checksum_outdated?
(
timestamp
)
def
repository_checksum_outdated?
(
timestamp
)
repository_verification_checksum
.
nil?
||
recalculate_repository_checksum?
(
timestamp
)
repository_verification_checksum
.
nil?
||
recalculate_repository_checksum?
(
timestamp
)
end
end
...
@@ -18,7 +21,15 @@ class ProjectRepositoryState < ActiveRecord::Base
...
@@ -18,7 +21,15 @@ class ProjectRepositoryState < ActiveRecord::Base
wiki_verification_checksum
.
nil?
||
recalculate_wiki_checksum?
(
timestamp
)
wiki_verification_checksum
.
nil?
||
recalculate_wiki_checksum?
(
timestamp
)
end
end
private
def
self
.
verified_repos
where
.
not
(
repository_verification_checksum:
nil
)
.
where
(
last_repository_verification_failed:
false
)
end
def
self
.
verified_wikis
where
.
not
(
wiki_verification_checksum:
nil
)
.
where
(
last_wiki_verification_failed:
false
)
end
def
recalculate_repository_checksum?
(
timestamp
)
def
recalculate_repository_checksum?
(
timestamp
)
last_repository_verification_at
.
nil?
||
timestamp
>
last_repository_verification_at
last_repository_verification_at
.
nil?
||
timestamp
>
last_repository_verification_at
...
...
ee/app/models/prometheus_metric.rb
0 → 100644
View file @
a8e34125
class
PrometheusMetric
<
ActiveRecord
::
Base
belongs_to
:project
,
required:
true
,
validate:
true
,
inverse_of: :prometheus_metrics
enum
group:
[
:business
,
:response
,
:system
]
validates
:title
,
presence:
true
validates
:query
,
presence:
true
validates
:group
,
presence:
true
validates
:y_label
,
presence:
true
validates
:unit
,
presence:
true
GROUP_TITLES
=
{
business:
_
(
'Business'
),
response:
_
(
'Response'
),
system:
_
(
'System'
)
}.
freeze
def
group_title
GROUP_TITLES
[
group
.
to_sym
]
end
def
to_query_metric
Gitlab
::
Prometheus
::
Metric
.
new
(
title:
title
,
required_metrics:
[],
weight:
0
,
y_label:
y_label
,
queries:
build_queries
)
end
private
def
build_queries
[
{
query_range:
query
,
unit:
unit
,
label:
legend
}
]
end
end
ee/app/serializers/prometheus_metric_entity.rb
0 → 100644
View file @
a8e34125
class
PrometheusMetricEntity
<
Grape
::
Entity
include
RequestAwareEntity
expose
:id
expose
:title
expose
:group
expose
:group_title
expose
:unit
expose
:edit_path
do
|
prometheus_metric
|
edit_project_prometheus_metric_path
(
prometheus_metric
.
project
,
prometheus_metric
)
end
end
ee/app/serializers/prometheus_metric_serializer.rb
0 → 100644
View file @
a8e34125
class
PrometheusMetricSerializer
<
BaseSerializer
entity
PrometheusMetricEntity
end
ee/app/services/geo/base_sync_service.rb
View file @
a8e34125
...
@@ -112,6 +112,11 @@ module Geo
...
@@ -112,6 +112,11 @@ module Geo
attrs
[
"last_
#{
type
}
_synced_at"
]
=
started_at
attrs
[
"last_
#{
type
}
_synced_at"
]
=
started_at
attrs
[
"
#{
type
}
_retry_count"
]
=
retry_count
+
1
attrs
[
"
#{
type
}
_retry_count"
]
=
retry_count
+
1
attrs
[
"
#{
type
}
_retry_at"
]
=
next_retry_time
(
attrs
[
"
#{
type
}
_retry_count"
])
attrs
[
"
#{
type
}
_retry_at"
]
=
next_retry_time
(
attrs
[
"
#{
type
}
_retry_count"
])
# indicate that repository verification needs to be done again
attrs
[
"
#{
type
}
_verification_checksum"
]
=
nil
attrs
[
"last_
#{
type
}
_verification_at"
]
=
nil
attrs
[
"last_
#{
type
}
_verification_failure"
]
=
nil
end
end
if
finished_at
if
finished_at
...
...
ee/app/services/geo/repository_verify_secondary_service.rb
0 → 100644
View file @
a8e34125
# rubocop:disable GitlabSecurity/PublicSend
module
Geo
class
RepositoryVerifySecondaryService
include
Gitlab
::
Geo
::
RepositoryVerificationLogHelpers
delegate
:project
,
to: :registry
def
initialize
(
registry
,
type
)
@registry
=
registry
@type
=
type
.
to_sym
end
def
execute
return
unless
Gitlab
::
Geo
.
geo_database_configured?
return
unless
Gitlab
::
Geo
.
secondary?
return
unless
should_verify_checksum?
verify_checksum
end
# This is primarily a guard method, to reduce the chance of false failures (which could happen
# for repositories that change very rapidly)
def
should_verify_checksum?
primary_checksum
=
registry
.
repository_state
.
public_send
(
"
#{
type
}
_verification_checksum"
)
secondary_checksum
=
registry
.
public_send
(
"
#{
type
}
_verification_checksum"
)
primary_last_verification_at
=
registry
.
repository_state
.
public_send
(
"last_
#{
type
}
_verification_at"
)
secondary_last_verification_at
=
registry
.
public_send
(
"last_
#{
type
}
_verification_at"
)
||
Time
.
at
(
0
)
secondary_last_successful_sync_at
=
registry
.
public_send
(
"last_
#{
type
}
_successful_sync_at"
)
# primary repository was verified (even if checksum is nil).
# note: we allow a nil primary checksum so that we will run through the checksum
# and set the verification date on the secondary. Otherwise, we'll keep revisiting
# this record over and over.
return
false
if
primary_last_verification_at
.
nil?
# secondary repository checksum does not equal the primary repository checksum
return
false
if
secondary_checksum
==
primary_checksum
&&
!
primary_checksum
.
nil?
# primary was verified later than the secondary verification
return
false
if
primary_last_verification_at
<
secondary_last_verification_at
# secondary repository was successfully synced after the last secondary verification
return
false
if
secondary_last_successful_sync_at
.
nil?
||
secondary_last_successful_sync_at
<
secondary_last_verification_at
true
end
private
attr_reader
:registry
,
:type
def
verify_checksum
checksum
=
calculate_checksum
(
project
.
repository_storage
,
repository_path
)
if
mismatch?
(
checksum
)
record_status
(
error_msg:
"
#{
type
.
to_s
.
capitalize
}
checksum mismatch:
#{
repository_path
}
"
)
else
record_status
(
checksum:
checksum
)
end
rescue
::
Gitlab
::
Git
::
Repository
::
NoRepository
,
::
Gitlab
::
Git
::
Checksum
::
Failure
,
Timeout
::
Error
=>
e
record_status
(
error_msg:
"Error verifying
#{
type
.
to_s
.
capitalize
}
checksum:
#{
repository_path
}
"
,
exception:
e
)
end
def
mismatch?
(
checksum
)
checksum
!=
registry
.
public_send
(
"project_
#{
type
}
_verification_checksum"
)
end
def
calculate_checksum
(
storage
,
relative_path
)
Gitlab
::
Git
::
Checksum
.
new
(
storage
,
relative_path
).
calculate
end
# note: the `last_#{type}_verification_at` is always set, indicating that was the
# time that we _did_ a verification, success or failure
def
record_status
(
checksum:
nil
,
error_msg:
nil
,
exception:
nil
,
details:
{})
attrs
=
{
"
#{
type
}
_verification_checksum"
=>
checksum
,
"last_
#{
type
}
_verification_at"
=>
DateTime
.
now
,
"last_
#{
type
}
_verification_failure"
=>
nil
,
"last_
#{
type
}
_verification_failed"
=>
false
}
if
error_msg
attrs
[
"last_
#{
type
}
_verification_failed"
]
=
true
attrs
[
"last_
#{
type
}
_verification_failure"
]
=
error_msg
log_error
(
error_msg
,
exception
,
type:
type
,
repository_path:
repository_path
,
full_path:
path_to_repo
)
end
registry
.
update!
(
attrs
)
end
def
repository_path
registry
.
repository_path
(
type
)
end
def
path_to_repo
case
type
when
:repository
project
.
repository
.
path_to_repo
when
:wiki
project
.
wiki
.
repository
.
path_to_repo
end
end
end
end
ee/app/views/projects/prometheus/metrics/_form.html.haml
0 → 100644
View file @
a8e34125
-
project
=
local_assigns
.
fetch
(
:project
)
-
metric
=
local_assigns
.
fetch
(
:metric
)
-
save_button_text
=
metric
.
persisted?
?
_
(
'Save changes'
)
:
s_
(
'Metrics|Create metric'
)
.row.prepend-top-default.append-bottom-default
%h3
.page-title.text-center
-
if
metric
.
persisted?
=
s_
(
'Metrics|Edit metric'
)
-
else
=
s_
(
'Metrics|New metric'
)
=
form_for
[
project
.
namespace
.
becomes
(
Namespace
),
project
,
metric
],
html:
{
class:
'col-lg-8 col-lg-offset-2'
}
do
|
f
|
=
form_errors
(
metric
)
.form-group
=
f
.
label
:title
,
s_
(
'Metrics|Name'
),
class:
'label-light'
=
f
.
text_field
:title
,
required:
true
,
class:
'form-control'
,
placeholder:
s_
(
'Metrics|e.g. Throughput'
),
autofocus:
true
%span
.help-block
=
s_
(
'Metrics|Used as a title for the chart'
)
.form-group
=
label_tag
:group
,
s_
(
"Metrics|Type"
),
class:
'append-bottom-10'
.form-group.append-bottom-0
=
f
.
radio_button
:group
,
:business
,
checked:
true
=
f
.
label
:group_business
,
s_
(
"Metrics|Business"
),
class:
'label-light append-right-10'
=
f
.
radio_button
:group
,
:response
=
f
.
label
:group_response
,
s_
(
"Metrics|Response"
),
class:
'label-light append-right-10'
=
f
.
radio_button
:group
,
:system
=
f
.
label
:group_system
,
s_
(
"Metrics|System"
),
class:
'label-light'
%p
.text-tertiary
=
s_
(
'Metrics|For grouping similar metrics'
)
.form-group
=
f
.
label
:query
,
s_
(
'Metrics|Query'
),
class:
'label-light'
=
f
.
text_field
:query
,
required:
true
,
class:
'form-control'
,
placeholder:
s_
(
'Metrics|e.g. rate(http_requests_total[5m])'
)
%span
.help-block
=
s_
(
'Metrics|Must be a valid PromQL query.'
)
=
link_to
"https://prometheus.io/docs/prometheus/latest/querying/basics/"
,
target:
"_blank"
,
rel:
"noopener noreferrer"
do
=
sprite_icon
(
"external-link"
,
size:
12
)
=
s_
(
'Metrics|Prometheus Query Documentation'
)
.form-group
=
f
.
label
:y_label
,
s_
(
'Metrics|Y-axis label'
),
class:
'label-light'
=
f
.
text_field
:y_label
,
class:
'form-control'
,
placeholder:
s_
(
'Metrics|e.g. Requests/second'
)
%span
.help-block
=
s_
(
"Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
)
.form-group
=
f
.
label
:unit
,
s_
(
'Metrics|Unit label'
),
class:
'label-light'
=
f
.
text_field
:unit
,
class:
'form-control'
,
placeholder:
s_
(
'Metrics|e.g. req/sec'
)
.form-group
=
f
.
label
:legend
,
s_
(
'Metrics|Legend label (optional)'
),
class:
'label-light'
=
f
.
text_field
:legend
,
class:
'form-control'
,
placeholder:
s_
(
'Metrics|e.g. HTTP requests'
)
%span
.help-block
=
s_
(
'Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response.'
)
.form-actions
=
f
.
submit
save_button_text
,
class:
'btn btn-success'
=
link_to
_
(
'Cancel'
),
edit_project_service_path
(
project
,
PrometheusService
),
class:
'btn btn-default pull-right'
-
if
metric
.
persisted?
=
link_to
_
(
'Delete'
),
project_prometheus_metric_path
(
project
,
metric
),
data:
{
confirm:
s_
(
"This will delete the custom metric, Are you sure?"
)
},
method: :delete
,
class:
"btn btn-danger pull-right append-right-default"
ee/app/views/projects/prometheus/metrics/edit.html.haml
0 → 100644
View file @
a8e34125
-
add_to_breadcrumbs
_
(
"Settings"
),
edit_project_path
(
@project
)
-
add_to_breadcrumbs
_
(
"Integrations"
),
project_settings_integrations_path
(
@project
)
-
add_to_breadcrumbs
"Prometheus"
,
edit_project_service_path
(
@project
,
PrometheusService
)
-
breadcrumb_title
=
s_
(
'Metrics|Edit metric'
)
-
page_title
@metric
.
title
,
s_
(
'Metrics|Edit metric'
)
=
render
'form'
,
project:
@project
,
metric:
@metric
ee/app/views/projects/prometheus/metrics/new.html.haml
0 → 100644
View file @
a8e34125
-
add_to_breadcrumbs
_
(
"Settings"
),
edit_project_path
(
@project
)
-
add_to_breadcrumbs
_
(
"Integrations"
),
project_settings_integrations_path
(
@project
)
-
add_to_breadcrumbs
"Prometheus"
,
edit_project_service_path
(
@project
,
PrometheusService
)
-
breadcrumb_title
=
s_
(
'Metrics|New metric'
)
-
page_title
s_
(
'Metrics|New metric'
)
=
render
'form'
,
project:
@project
,
metric:
@metric
ee/app/workers/geo/repository_verification/secondary/scheduler_worker.rb
0 → 100644
View file @
a8e34125
module
Geo
module
RepositoryVerification
module
Secondary
class
SchedulerWorker
<
Geo
::
Scheduler
::
SecondaryWorker
include
CronjobQueue
MAX_CAPACITY
=
1000
def
perform
return
unless
Feature
.
enabled?
(
'geo_repository_verification'
)
super
end
private
def
max_capacity
MAX_CAPACITY
end
def
load_pending_resources
finder
.
find_registries_to_verify
.
limit
(
db_retrieve_batch_size
).
pluck
(
:id
)
end
def
schedule_job
(
registry_id
)
job_id
=
Geo
::
RepositoryVerification
::
Secondary
::
SingleWorker
.
perform_async
(
registry_id
)
{
id:
registry_id
,
job_id:
job_id
}
if
job_id
end
def
finder
@finder
||=
Geo
::
ProjectRegistryFinder
.
new
end
end
end
end
end
ee/app/workers/geo/repository_verification/secondary/single_worker.rb
0 → 100644
View file @
a8e34125
module
Geo
module
RepositoryVerification
module
Secondary
class
SingleWorker
include
ApplicationWorker
include
GeoQueue
include
ExclusiveLeaseGuard
include
Gitlab
::
Geo
::
ProjectLogHelpers
LEASE_TIMEOUT
=
1
.
hour
.
to_i
attr_reader
:registry
private
:registry
delegate
:project
,
to: :registry
def
perform
(
registry_id
)
@registry
=
Geo
::
ProjectRegistry
.
find
(
registry_id
)
return
if
registry
.
nil?
||
project
.
pending_delete?
try_obtain_lease
do
verify_checksum
(
:repository
)
verify_checksum
(
:wiki
)
end
end
private
def
verify_checksum
(
type
)
Geo
::
RepositoryVerifySecondaryService
.
new
(
registry
,
type
).
execute
rescue
=>
e
log_error
(
'Error verifying the repository checksum'
,
e
,
type:
type
)
raise
e
end
def
lease_key
"geo:repository_verification:secondary:single_worker:
#{
project
.
id
}
"
end
def
lease_timeout
LEASE_TIMEOUT
end
end
end
end
end
ee/changelogs/unreleased/geo-repository-checksum.yml
0 → 100644
View file @
a8e34125
---
title
:
Geo - Verify repository checksums on the secondary node
merge_request
:
4749
author
:
type
:
added
ee/changelogs/unreleased/pawel-prometheus-business-metrics-ee-2273.yml
0 → 100644
View file @
a8e34125
---
title
:
Add ability to add Custom Metrics to environment and deployment metrics dashboards
merge_request
:
3799
author
:
type
:
added
ee/db/geo/migrate/20180201154345_add_repository_verification_to_project_registry.rb
0 → 100644
View file @
a8e34125
class
AddRepositoryVerificationToProjectRegistry
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
def
change
add_column
:project_registry
,
:repository_verification_checksum
,
:string
add_column
:project_registry
,
:last_repository_verification_at
,
:datetime_with_timezone
add_column
:project_registry
,
:last_repository_verification_failed
,
:boolean
,
null:
false
,
default:
false
add_column
:project_registry
,
:last_repository_verification_failure
,
:string
add_column
:project_registry
,
:wiki_verification_checksum
,
:string
add_column
:project_registry
,
:last_wiki_verification_at
,
:datetime_with_timezone
add_column
:project_registry
,
:last_wiki_verification_failed
,
:boolean
,
null:
false
,
default:
false
add_column
:project_registry
,
:last_wiki_verification_failure
,
:string
end
end
ee/db/geo/schema.rb
View file @
a8e34125
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201
71115143841
)
do
ActiveRecord
::
Schema
.
define
(
version:
201
80201154345
)
do
# These are extensions that must be enabled in order to support this database
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
enable_extension
"plpgsql"
...
@@ -52,6 +52,14 @@ ActiveRecord::Schema.define(version: 20171115143841) do
...
@@ -52,6 +52,14 @@ ActiveRecord::Schema.define(version: 20171115143841) do
t
.
boolean
"force_to_redownload_wiki"
t
.
boolean
"force_to_redownload_wiki"
t
.
string
"last_repository_sync_failure"
t
.
string
"last_repository_sync_failure"
t
.
string
"last_wiki_sync_failure"
t
.
string
"last_wiki_sync_failure"
t
.
string
"repository_verification_checksum"
t
.
datetime_with_timezone
"last_repository_verification_at"
t
.
boolean
"last_repository_verification_failed"
,
default:
false
,
null:
false
t
.
string
"last_repository_verification_failure"
t
.
string
"wiki_verification_checksum"
t
.
datetime_with_timezone
"last_wiki_verification_at"
t
.
boolean
"last_wiki_verification_failed"
,
default:
false
,
null:
false
t
.
string
"last_wiki_verification_failure"
end
end
add_index
"project_registry"
,
[
"last_repository_successful_sync_at"
],
name:
"index_project_registry_on_last_repository_successful_sync_at"
,
using: :btree
add_index
"project_registry"
,
[
"last_repository_successful_sync_at"
],
name:
"index_project_registry_on_last_repository_successful_sync_at"
,
using: :btree
...
...
ee/db/migrate/20180101160629_create_prometheus_metrics.rb
0 → 100644
View file @
a8e34125
class
CreatePrometheusMetrics
<
ActiveRecord
::
Migration
DOWNTIME
=
false
def
change
create_table
:prometheus_metrics
do
|
t
|
t
.
references
:project
,
index:
true
,
foreign_key:
{
on_delete: :cascade
},
null:
false
t
.
string
:title
,
null:
false
t
.
string
:query
,
null:
false
t
.
string
:y_label
t
.
string
:unit
t
.
string
:legend
t
.
integer
:group
,
null:
false
,
index:
true
t
.
timestamps_with_timezone
null:
false
end
end
end
ee/db/migrate/20180225180932_add_geo_node_verification_status.rb
0 → 100644
View file @
a8e34125
class
AddGeoNodeVerificationStatus
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
def
change
add_column
:geo_node_statuses
,
:repositories_verified_count
,
:integer
add_column
:geo_node_statuses
,
:repositories_verification_failed_count
,
:integer
add_column
:geo_node_statuses
,
:wikis_verified_count
,
:integer
add_column
:geo_node_statuses
,
:wikis_verification_failed_count
,
:integer
end
end
ee/lib/ee/api/entities.rb
View file @
a8e34125
...
@@ -293,6 +293,18 @@ module EE
...
@@ -293,6 +293,18 @@ module EE
number_to_percentage
(
node
.
wikis_synced_in_percentage
,
precision:
2
)
number_to_percentage
(
node
.
wikis_synced_in_percentage
,
precision:
2
)
end
end
expose
:repositories_verification_failed_count
expose
:repositories_verified_count
expose
:repositories_verified_in_percentage
do
|
node
|
number_to_percentage
(
node
.
repositories_verified_in_percentage
,
precision:
2
)
end
expose
:wikis_verification_failed_count
expose
:wikis_verified_count
expose
:wikis_verified_in_percentage
do
|
node
|
number_to_percentage
(
node
.
wikis_verified_in_percentage
,
precision:
2
)
end
expose
:replication_slots_count
expose
:replication_slots_count
expose
:replication_slots_used_count
expose
:replication_slots_used_count
expose
:replication_slots_used_in_percentage
do
|
node
|
expose
:replication_slots_used_in_percentage
do
|
node
|
...
...
ee/lib/gitlab/geo/cron_manager.rb
View file @
a8e34125
...
@@ -6,6 +6,7 @@ module Gitlab
...
@@ -6,6 +6,7 @@ module Gitlab
SECONDARY_JOBS
=
%w[
SECONDARY_JOBS
=
%w[
geo_repository_sync_worker
geo_repository_sync_worker
geo_file_download_dispatch_worker
geo_file_download_dispatch_worker
geo_repository_verification_secondary_scheduler_worker
]
.
freeze
]
.
freeze
GEO_JOBS
=
(
COMMON_JOBS
+
PRIMARY_JOBS
+
SECONDARY_JOBS
).
freeze
GEO_JOBS
=
(
COMMON_JOBS
+
PRIMARY_JOBS
+
SECONDARY_JOBS
).
freeze
...
...
ee/lib/gitlab/geo/log_helpers.rb
View file @
a8e34125
...
@@ -4,14 +4,14 @@ module Gitlab
...
@@ -4,14 +4,14 @@ module Gitlab
def
log_info
(
message
,
details
=
{})
def
log_info
(
message
,
details
=
{})
data
=
base_log_data
(
message
)
data
=
base_log_data
(
message
)
data
.
merge!
(
details
)
if
details
data
.
merge!
(
details
)
if
details
Gitlab
::
Geo
::
L
ogger
.
info
(
data
)
geo_l
ogger
.
info
(
data
)
end
end
def
log_error
(
message
,
error
=
nil
,
details
=
{})
def
log_error
(
message
,
error
=
nil
,
details
=
{})
data
=
base_log_data
(
message
)
data
=
base_log_data
(
message
)
data
[
:error
]
=
error
.
to_s
if
error
data
[
:error
]
=
error
.
to_s
if
error
data
.
merge!
(
details
)
if
details
data
.
merge!
(
details
)
if
details
Gitlab
::
Geo
::
L
ogger
.
error
(
data
)
geo_l
ogger
.
error
(
data
)
end
end
protected
protected
...
@@ -22,6 +22,10 @@ module Gitlab
...
@@ -22,6 +22,10 @@ module Gitlab
message:
message
message:
message
}
}
end
end
def
geo_logger
Gitlab
::
Geo
::
Logger
end
end
end
end
end
end
end
ee/lib/gitlab/geo/repository_verification_log_helpers.rb
0 → 100644
View file @
a8e34125
module
Gitlab
module
Geo
module
RepositoryVerificationLogHelpers
include
ProjectLogHelpers
protected
def
geo_logger
Gitlab
::
Geo
::
RepositoryVerificationLogger
end
end
end
end
ee/lib/gitlab/geo/repository_verification_logger.rb
0 → 100644
View file @
a8e34125
module
Gitlab
module
Geo
class
RepositoryVerificationLogger
<
::
Gitlab
::
Geo
::
Logger
def
self
.
file_name_noext
'geo_repository_verification'
end
end
end
end
ee/lib/gitlab/prometheus/queries/validate_query.rb
0 → 100644
View file @
a8e34125
module
Gitlab
module
Prometheus
module
Queries
class
ValidateQuery
<
BaseQuery
def
query
(
query
)
client_query
(
query
)
{
valid:
true
}
rescue
Gitlab
::
PrometheusClient
::
QueryError
=>
ex
{
valid:
false
,
error:
ex
.
message
}
end
def
self
.
transform_reactive_result
(
result
)
result
[
:query
]
=
result
.
delete
:data
result
end
end
end
end
end
ee/spec/controllers/projects/prometheus/metrics_controller_spec.rb
0 → 100644
View file @
a8e34125
require
'spec_helper'
describe
Projects
::
Prometheus
::
MetricsController
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:prometheus_project
)
}
let
(
:prometheus_adapter
)
{
double
(
'prometheus_adapter'
,
can_query?:
true
)
}
before
do
allow
(
controller
).
to
receive
(
:project
).
and_return
(
project
)
allow
(
controller
).
to
receive
(
:prometheus_adapter
).
and_return
(
prometheus_adapter
)
project
.
add_master
(
user
)
sign_in
(
user
)
end
describe
'POST #validate_query'
do
before
do
allow
(
prometheus_adapter
).
to
receive
(
:query
).
with
(
:validate
,
query
)
{
validation_result
}
end
let
(
:query
)
{
'avg(metric)'
}
context
'validation information is ready'
do
let
(
:validation_result
)
{
{
valid:
true
}
}
it
'validation data is returned'
do
post
:validate_query
,
project_params
(
format: :json
,
query:
query
)
expect
(
json_response
).
to
eq
(
'valid'
=>
true
)
end
end
context
'validation information is not ready'
do
let
(
:validation_result
)
{
{}
}
it
'validation data is returned'
do
post
:validate_query
,
project_params
(
format: :json
,
query:
query
)
expect
(
response
).
to
have_gitlab_http_status
(
204
)
end
end
end
describe
'GET #index'
do
context
'with custom metric present'
do
let!
(
:prometheus_metric
)
{
create
(
:prometheus_metric
,
project:
project
)
}
it
'returns a list of metrics'
do
get
:index
,
project_params
(
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
match_response_schema
(
'prometheus/metrics'
,
dir:
'ee'
)
end
end
context
'without custom metrics '
do
it
'returns an empty json'
do
get
:index
,
project_params
(
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
).
to
eq
({})
end
end
end
describe
'POST #create'
do
context
'metric is valid'
do
let
(
:valid_metric
)
{
{
prometheus_metric:
{
title:
'title'
,
query:
'query'
,
group:
'business'
,
y_label:
'label'
,
unit:
'u'
,
legend:
'legend'
}
}
}
it
'shows a success flash message'
do
post
:create
,
project_params
(
valid_metric
)
expect
(
flash
[
:notice
]).
to
include
(
'Metric was successfully added.'
)
expect
(
response
).
to
redirect_to
(
edit_project_service_path
(
project
,
PrometheusService
))
end
end
context
'metric is invalid'
do
let
(
:invalid_metric
)
{
{
prometheus_metric:
{
title:
'title'
}
}
}
it
'renders new metric page'
do
post
:create
,
project_params
(
invalid_metric
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
render_template
(
'new'
)
end
end
end
describe
'DELETE #destroy'
do
context
'format html'
do
let!
(
:metric
)
{
create
(
:prometheus_metric
,
project:
project
)
}
it
'destroys the metric'
do
delete
:destroy
,
project_params
(
id:
metric
.
id
)
expect
(
response
).
to
redirect_to
(
edit_project_service_path
(
project
,
PrometheusService
))
expect
(
PrometheusMetric
.
find_by
(
id:
metric
.
id
)).
to
be_nil
end
end
context
'format json'
do
let!
(
:metric
)
{
create
(
:prometheus_metric
,
project:
project
)
}
it
'destroys the metric'
do
delete
:destroy
,
project_params
(
id:
metric
.
id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
PrometheusMetric
.
find_by
(
id:
metric
.
id
)).
to
be_nil
end
end
end
def
project_params
(
opts
=
{})
opts
.
reverse_merge
(
namespace_id:
project
.
namespace
,
project_id:
project
)
end
end
ee/spec/factories/geo/project_registry.rb
View file @
a8e34125
...
@@ -72,5 +72,31 @@ FactoryBot.define do
...
@@ -72,5 +72,31 @@ FactoryBot.define do
wiki_sync_failed
wiki_sync_failed
wiki_retry_count
0
wiki_retry_count
0
end
end
trait
:repository_verified
do
repository_verification_checksum
'f079a831cab27bcda7d81cd9b48296d0c3dd92ee'
last_repository_verification_failed
false
last_repository_verification_at
{
5
.
days
.
ago
}
end
trait
:wiki_verified
do
wiki_verification_checksum
'e079a831cab27bcda7d81cd9b48296d0c3dd92ef'
last_wiki_verification_failed
false
last_wiki_verification_at
{
5
.
days
.
ago
}
end
trait
:repository_verification_failed
do
repository_verification_checksum
nil
last_repository_verification_at
{
5
.
days
.
ago
}
last_repository_verification_failed
true
last_repository_verification_failure
'Repository checksum did not match'
end
trait
:wiki_verification_failed
do
wiki_verification_checksum
nil
last_wiki_verification_at
{
5
.
days
.
ago
}
last_wiki_verification_failed
true
last_wiki_verification_failure
'Wiki checksum did not match'
end
end
end
end
end
ee/spec/factories/prometheus_metrics.rb
0 → 100644
View file @
a8e34125
FactoryBot
.
define
do
factory
:prometheus_metric
,
class:
PrometheusMetric
do
title
'title'
query
'avg(metric)'
y_label
'y_label'
unit
'm/s'
group
:business
project
legend
'legend'
end
end
ee/spec/finders/geo/project_registry_finder_spec.rb
View file @
a8e34125
...
@@ -9,6 +9,10 @@ describe Geo::ProjectRegistryFinder, :geo do
...
@@ -9,6 +9,10 @@ describe Geo::ProjectRegistryFinder, :geo do
let
(
:project_synced
)
{
create
(
:project
)
}
let
(
:project_synced
)
{
create
(
:project
)
}
let
(
:project_repository_dirty
)
{
create
(
:project
)
}
let
(
:project_repository_dirty
)
{
create
(
:project
)
}
let
(
:project_wiki_dirty
)
{
create
(
:project
)
}
let
(
:project_wiki_dirty
)
{
create
(
:project
)
}
let
(
:project_repository_verified
)
{
create
(
:project
)
}
let
(
:project_repository_verification_failed
)
{
create
(
:project
)
}
let
(
:project_wiki_verified
)
{
create
(
:project
)
}
let
(
:project_wiki_verification_failed
)
{
create
(
:project
)
}
subject
{
described_class
.
new
(
current_node:
secondary
)
}
subject
{
described_class
.
new
(
current_node:
secondary
)
}
...
@@ -187,6 +191,82 @@ describe Geo::ProjectRegistryFinder, :geo do
...
@@ -187,6 +191,82 @@ describe Geo::ProjectRegistryFinder, :geo do
end
end
end
end
describe
'#count_verification_failed_repositories'
do
it
'delegates to #find_verification_failed_project_registries'
do
expect
(
subject
).
to
receive
(
:find_verification_failed_project_registries
).
with
(
'repository'
).
and_call_original
subject
.
count_verification_failed_repositories
end
it
'counts projects that verification has failed'
do
create
(
:geo_project_registry
,
:repository_verified
,
project:
project_repository_verified
)
create
(
:geo_project_registry
,
:repository_verification_failed
,
project:
project_repository_verification_failed
)
create
(
:geo_project_registry
,
:wiki_verified
,
project:
project_wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
,
project:
project_wiki_verification_failed
)
expect
(
subject
.
count_verification_failed_repositories
).
to
eq
1
end
context
'with legacy queries'
do
before
do
allow
(
subject
).
to
receive
(
:use_legacy_queries?
).
and_return
(
true
)
end
it
'delegates to #legacy_find_filtered_verification_failed_projects'
do
expect
(
subject
).
to
receive
(
:legacy_find_filtered_verification_failed_projects
).
and_call_original
subject
.
find_verification_failed_project_registries
(
'repository'
)
end
it
'counts projects that verification has failed'
do
create
(
:geo_project_registry
,
:repository_verified
,
project:
project_repository_verified
)
create
(
:geo_project_registry
,
:repository_verification_failed
,
project:
project_repository_verification_failed
)
create
(
:geo_project_registry
,
:wiki_verified
,
project:
project_wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
,
project:
project_wiki_verification_failed
)
expect
(
subject
.
count_verification_failed_repositories
).
to
eq
1
end
end
end
describe
'#count_verification_failed_wikis'
do
it
'delegates to #find_verification_failed_project_registries'
do
expect
(
subject
).
to
receive
(
:find_verification_failed_project_registries
).
with
(
'wiki'
).
and_call_original
subject
.
count_verification_failed_wikis
end
it
'counts projects that verification has failed'
do
create
(
:geo_project_registry
,
:repository_verified
,
project:
project_repository_verified
)
create
(
:geo_project_registry
,
:repository_verification_failed
,
project:
project_repository_verification_failed
)
create
(
:geo_project_registry
,
:wiki_verified
,
project:
project_wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
,
project:
project_wiki_verification_failed
)
expect
(
subject
.
count_verification_failed_wikis
).
to
eq
1
end
context
'with legacy queries'
do
before
do
allow
(
subject
).
to
receive
(
:use_legacy_queries?
).
and_return
(
true
)
end
it
'delegates to #legacy_find_filtered_verification_failed_projects'
do
expect
(
subject
).
to
receive
(
:legacy_find_filtered_verification_failed_projects
).
and_call_original
subject
.
find_verification_failed_project_registries
(
'wiki'
)
end
it
'counts projects that verification has failed'
do
create
(
:geo_project_registry
,
:repository_verified
,
project:
project_repository_verified
)
create
(
:geo_project_registry
,
:repository_verification_failed
,
project:
project_repository_verification_failed
)
create
(
:geo_project_registry
,
:wiki_verified
,
project:
project_wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
,
project:
project_wiki_verification_failed
)
expect
(
subject
.
count_verification_failed_wikis
).
to
eq
1
end
end
end
describe
'#find_failed_project_registries'
do
describe
'#find_failed_project_registries'
do
let
(
:project_1_in_synced_group
)
{
create
(
:project
,
group:
synced_group
)
}
let
(
:project_1_in_synced_group
)
{
create
(
:project
,
group:
synced_group
)
}
let
(
:project_2_in_synced_group
)
{
create
(
:project
,
group:
synced_group
)
}
let
(
:project_2_in_synced_group
)
{
create
(
:project
,
group:
synced_group
)
}
...
@@ -311,6 +391,161 @@ describe Geo::ProjectRegistryFinder, :geo do
...
@@ -311,6 +391,161 @@ describe Geo::ProjectRegistryFinder, :geo do
end
end
end
end
shared_examples
'find registries for repositories/wikis'
do
|
use_fdw
|
before
do
allow
(
Gitlab
::
Geo
::
Fdw
).
to
receive
(
:enabled?
).
and_return
(
use_fdw
)
end
let
(
:verified_repository_state
)
{
create
(
:repository_state
,
:repository_verified
,
:wiki_verified
,
last_repository_verification_at:
10
.
minutes
.
from_now
)
}
let
(
:verified_project
)
{
create
(
:project
,
repository_state:
verified_repository_state
)
}
let
(
:verified_registry
)
do
create
(
:geo_project_registry
,
project:
verified_project
,
last_repository_verification_at:
Time
.
now
,
last_repository_successful_sync_at:
5
.
minutes
.
from_now
)
end
context
'with the primary verification failure'
do
it
'finds when not failed'
do
verified_repository_state
.
last_repository_verification_failed
=
false
verified_repository_state
.
last_wiki_verification_failed
=
false
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not find when failed'
do
verified_repository_state
.
last_repository_verification_failed
=
true
verified_repository_state
.
last_wiki_verification_failed
=
true
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
it
'finds when either repo/wiki fails'
do
verified_repository_state
.
last_repository_verification_failed
=
true
verified_repository_state
.
last_wiki_verification_failed
=
false
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
end
context
'with the primary verification checksum'
do
it
'finds with a checksum'
do
verified_repository_state
.
repository_verification_checksum
=
'my-checksum'
verified_repository_state
.
wiki_verification_checksum
=
'my-checksum'
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not find a checksum'
do
verified_repository_state
.
repository_verification_checksum
=
nil
verified_repository_state
.
wiki_verification_checksum
=
nil
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
it
'finds when either repo/wiki has a checksum'
do
verified_repository_state
.
repository_verification_checksum
=
'my-checksum'
verified_repository_state
.
wiki_verification_checksum
=
nil
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
end
context
'with the primary repository verification date '
do
let
(
:verified_project
)
do
project
=
create
(
:project
,
repository_state:
verified_repository_state
)
project
.
update_attribute
(
:last_repository_updated_at
,
30
.
minutes
.
ago
)
project
end
let
(
:verified_registry
)
do
create
(
:geo_project_registry
,
project:
verified_project
,
last_repository_verification_at:
25
.
minutes
.
ago
,
last_wiki_verification_at:
25
.
minutes
.
ago
,
last_repository_successful_sync_at:
5
.
minutes
.
from_now
,
last_wiki_successful_sync_at:
5
.
minutes
.
from_now
)
end
it
'finds if primary verified after the primary repository was updated'
do
verified_repository_state
.
last_repository_verification_at
=
20
.
minutes
.
ago
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not find if primary repository updated after primary verification'
do
verified_repository_state
.
last_repository_verification_at
=
35
.
minutes
.
ago
verified_repository_state
.
last_wiki_verification_at
=
35
.
minutes
.
ago
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
it
'finds if primary wiki verified after the primary repository was updated'
do
verified_repository_state
.
last_repository_verification_at
=
35
.
minutes
.
ago
verified_repository_state
.
last_wiki_verification_at
=
20
.
minutes
.
ago
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not find if primary verification did not happen'
do
verified_repository_state
.
last_repository_verification_at
=
nil
verified_repository_state
.
last_wiki_verification_at
=
nil
verified_registry
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
it
'finds if primary was verified after the secondary was verified'
do
verified_registry
.
update_attribute
(
:last_repository_verification_at
,
verified_repository_state
.
last_repository_verification_at
-
5
.
minutes
)
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not find if primary was verified before the secondary was verified'
do
verified_registry
.
update_attributes
(
last_repository_verification_at:
verified_repository_state
.
last_repository_verification_at
+
5
.
minutes
,
last_wiki_verification_at:
verified_repository_state
.
last_wiki_verification_at
+
5
.
minutes
)
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
end
it
'returns repositories failed more than 24 hours ago'
do
create
(
:geo_project_registry
,
project:
verified_project
,
repository_verification_checksum:
nil
,
last_repository_verification_failed:
true
,
last_repository_verification_at:
2
.
days
.
ago
)
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
1
end
it
'does not return repositories failed less than 24 hours ago'
do
create
(
:geo_project_registry
,
:repository_verification_failed
,
last_repository_verification_at:
5
.
hours
.
ago
)
expect
(
subject
.
find_registries_to_verify
.
count
).
to
eq
0
end
end
describe
'#find_registries_to_verify'
,
:delete
do
context
'using FDW'
do
include_examples
'find registries for repositories/wikis'
,
true
end
context
'using Legacy'
do
include_examples
'find registries for repositories/wikis'
,
false
end
end
context
'Legacy'
do
context
'Legacy'
do
before
do
before
do
allow
(
Gitlab
::
Geo
::
Fdw
).
to
receive
(
:enabled?
).
and_return
(
false
)
allow
(
Gitlab
::
Geo
::
Fdw
).
to
receive
(
:enabled?
).
and_return
(
false
)
...
...
ee/spec/fixtures/api/schemas/prometheus/metrics.json
0 → 100644
View file @
a8e34125
{
"type"
:
"object"
,
"properties"
:
{
"metrics"
:
{
"type"
:
"array"
,
"items"
:
{
"type"
:
"object"
,
"properties"
:
{
"id"
:
{
"type"
:
"integer"
},
"title"
:
{
"type"
:
"string"
},
"group"
:
{
"type"
:
"string"
},
"group_title"
:
{
"type"
:
"string"
},
"edit_path"
:
{
"type"
:
"string"
}
}
}
}
}
}
ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json
View file @
a8e34125
...
@@ -22,6 +22,12 @@
...
@@ -22,6 +22,12 @@
"wikis_count"
,
"wikis_count"
,
"wikis_failed_count"
,
"wikis_failed_count"
,
"wikis_synced_count"
,
"wikis_synced_count"
,
"repositories_verified_count"
,
"repositories_verification_failed_count"
,
"repositories_verified_in_percentage"
,
"wikis_verified_count"
,
"wikis_verification_failed_count"
,
"wikis_verified_in_percentage"
,
"replication_slots_count"
,
"replication_slots_count"
,
"replication_slots_used_count"
,
"replication_slots_used_count"
,
"replication_slots_used_in_percentage"
,
"replication_slots_used_in_percentage"
,
...
@@ -64,6 +70,12 @@
...
@@ -64,6 +70,12 @@
"wikis_failed_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_failed_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_synced_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_synced_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_synced_in_percentage"
:
{
"type"
:
"string"
},
"wikis_synced_in_percentage"
:
{
"type"
:
"string"
},
"repositories_verified_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"repositories_verification_failed_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"repositories_verified_in_percentage"
:
{
"type"
:
"string"
},
"wikis_verified_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_verification_failed_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"wikis_verified_in_percentage"
:
{
"type"
:
"string"
},
"replication_slots_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"replication_slots_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"replication_slots_used_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"replication_slots_used_count"
:
{
"type"
:
[
"integer"
,
"null"
]
},
"replication_slots_used_in_percentage"
:
{
"type"
:
"string"
},
"replication_slots_used_in_percentage"
:
{
"type"
:
"string"
},
...
...
ee/spec/lib/gitlab/geo/cron_manager_spec.rb
View file @
a8e34125
...
@@ -28,6 +28,7 @@ describe Gitlab::Geo::CronManager, :geo do
...
@@ -28,6 +28,7 @@ describe Gitlab::Geo::CronManager, :geo do
geo_repository_verification_primary_batch_worker
geo_repository_verification_primary_batch_worker
geo_repository_sync_worker
geo_repository_sync_worker
geo_file_download_dispatch_worker
geo_file_download_dispatch_worker
geo_repository_verification_secondary_scheduler_worker
geo_metrics_update_worker
geo_metrics_update_worker
]
.
freeze
]
.
freeze
...
@@ -46,7 +47,8 @@ describe Gitlab::Geo::CronManager, :geo do
...
@@ -46,7 +47,8 @@ describe Gitlab::Geo::CronManager, :geo do
let
(
:secondary_jobs
)
do
let
(
:secondary_jobs
)
do
[
[
job
(
'geo_file_download_dispatch_worker'
),
job
(
'geo_file_download_dispatch_worker'
),
job
(
'geo_repository_sync_worker'
)
job
(
'geo_repository_sync_worker'
),
job
(
'geo_repository_verification_secondary_scheduler_worker'
)
]
]
end
end
...
...
ee/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
0 → 100644
View file @
a8e34125
require
'spec_helper'
describe
Gitlab
::
Prometheus
::
Queries
::
ValidateQuery
do
let
(
:client
)
{
double
(
'prometheus_client'
)
}
let
(
:query
)
{
'avg(metric)'
}
subject
{
described_class
.
new
(
client
)
}
context
'valid query'
do
before
do
allow
(
client
).
to
receive
(
:query
).
with
(
query
)
end
it
'passess query to prometheus'
do
expect
(
subject
.
query
(
query
)).
to
eq
(
valid:
true
)
expect
(
client
).
to
have_received
(
:query
).
with
(
query
)
end
end
context
'invalid query'
do
let
(
:message
)
{
'message'
}
before
do
allow
(
client
).
to
receive
(
:query
).
with
(
query
).
and_raise
(
Gitlab
::
PrometheusClient
::
QueryError
.
new
(
message
))
end
it
'passes query to prometheus'
do
expect
(
subject
.
query
(
query
)).
to
eq
(
valid:
false
,
error:
message
)
expect
(
client
).
to
have_received
(
:query
).
with
(
query
)
end
end
end
ee/spec/models/geo/project_registry_spec.rb
View file @
a8e34125
...
@@ -45,6 +45,54 @@ describe Geo::ProjectRegistry do
...
@@ -45,6 +45,54 @@ describe Geo::ProjectRegistry do
end
end
end
end
describe
'.verified_repos'
do
it
'returns projects that verified'
do
create
(
:geo_project_registry
,
:repository_verification_failed
)
create
(
:geo_project_registry
,
:wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
)
repository_verified
=
create
(
:geo_project_registry
,
:repository_verified
)
expect
(
described_class
.
verified_repos
).
to
match_array
([
repository_verified
])
end
end
describe
'.verification_failed_repos'
do
it
'returns projects where last attempt to verify failed'
do
create
(
:geo_project_registry
,
:repository_verified
)
create
(
:geo_project_registry
,
:wiki_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
)
repository_verification_failed
=
create
(
:geo_project_registry
,
:repository_verification_failed
)
expect
(
described_class
.
verification_failed_repos
).
to
match_array
([
repository_verification_failed
])
end
end
describe
'.verified_wikis'
do
it
'returns projects that verified'
do
create
(
:geo_project_registry
,
:repository_verification_failed
)
create
(
:geo_project_registry
,
:repository_verified
)
create
(
:geo_project_registry
,
:wiki_verification_failed
)
wiki_verified
=
create
(
:geo_project_registry
,
:wiki_verified
)
expect
(
described_class
.
verified_wikis
).
to
match_array
([
wiki_verified
])
end
end
describe
'.verification_failed_wikis'
do
it
'returns projects where last attempt to verify failed'
do
create
(
:geo_project_registry
,
:repository_verified
)
create
(
:geo_project_registry
,
:wiki_verified
)
create
(
:geo_project_registry
,
:repository_verification_failed
)
wiki_verification_failed
=
create
(
:geo_project_registry
,
:wiki_verification_failed
)
expect
(
described_class
.
verification_failed_wikis
).
to
match_array
([
wiki_verification_failed
])
end
end
describe
'.retry_due'
do
describe
'.retry_due'
do
it
'returns projects that should be synced'
do
it
'returns projects that should be synced'
do
create
(
:geo_project_registry
,
repository_retry_at:
Date
.
yesterday
,
wiki_retry_at:
Date
.
yesterday
)
create
(
:geo_project_registry
,
repository_retry_at:
Date
.
yesterday
,
wiki_retry_at:
Date
.
yesterday
)
...
...
ee/spec/models/prometheus_metric_spec.rb
0 → 100644
View file @
a8e34125
require
'spec_helper'
describe
PrometheusMetric
do
subject
{
build
(
:prometheus_metric
)
}
it
{
is_expected
.
to
belong_to
(
:project
)
}
it
{
is_expected
.
to
validate_presence_of
(
:title
)
}
it
{
is_expected
.
to
validate_presence_of
(
:query
)
}
it
{
is_expected
.
to
validate_presence_of
(
:group
)
}
describe
'#group_title'
do
shared_examples
'group_title'
do
|
group
,
title
|
subject
{
build
(
:prometheus_metric
,
group:
group
).
group_title
}
it
"returns text
#{
title
}
for group
#{
group
}
"
do
expect
(
subject
).
to
eq
(
title
)
end
end
it_behaves_like
'group_title'
,
:business
,
'Business'
it_behaves_like
'group_title'
,
:response
,
'Response'
it_behaves_like
'group_title'
,
:system
,
'System'
end
describe
'#to_query_metric'
do
it
'converts to queryable metric object'
do
expect
(
subject
.
to_query_metric
).
to
be_instance_of
(
Gitlab
::
Prometheus
::
Metric
)
end
it
'queryable metric object has title'
do
expect
(
subject
.
to_query_metric
.
title
).
to
eq
(
subject
.
title
)
end
it
'queryable metric object has y_label'
do
expect
(
subject
.
to_query_metric
.
y_label
).
to
eq
(
subject
.
y_label
)
end
it
'queryable metric has no required_metric'
do
expect
(
subject
.
to_query_metric
.
required_metrics
).
to
eq
([])
end
it
'queryable metric has weight 0'
do
expect
(
subject
.
to_query_metric
.
weight
).
to
eq
(
0
)
end
it
'queryable metrics has query description'
do
queries
=
[
{
query_range:
subject
.
query
,
unit:
subject
.
unit
,
label:
subject
.
legend
}
]
expect
(
subject
.
to_query_metric
.
queries
).
to
eq
(
queries
)
end
end
end
ee/spec/services/ci_cd/github_setup_service_spec.rb
View file @
a8e34125
require
'spec_helper'
require
'spec_helper'
describe
CiCd
::
GithubSetupService
do
describe
CiCd
::
GithubSetupService
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:repo_full_name
)
{
"MyUser/my-project"
}
let
(
:api_token
)
{
"abcdefghijk123"
}
let
(
:import_url
)
{
"https://
#{
api_token
}
@github.com/
#{
repo_full_name
}
.git"
}
let
(
:credentials
)
{
{
user:
api_token
}
}
let
(
:project
)
do
create
(
:project
,
import_source:
repo_full_name
,
import_url:
import_url
,
import_data_attributes:
{
credentials:
credentials
}
)
end
subject
do
subject
do
described_class
.
new
(
project
)
described_class
.
new
(
project
)
...
...
ee/spec/services/geo/repository_verify_secondary_service_spec.rb
0 → 100644
View file @
a8e34125
require
'spec_helper'
describe
Geo
::
RepositoryVerifySecondaryService
,
:geo
do
include
::
EE
::
GeoHelpers
let
(
:primary
)
{
create
(
:geo_node
,
:primary
)
}
let
(
:secondary
)
{
create
(
:geo_node
)
}
before
do
stub_current_geo_node
(
secondary
)
end
describe
'#execute'
do
let
(
:repository_state
)
{
create
(
:repository_state
,
project:
create
(
:project
,
:repository
))}
let
(
:registry
)
do
registry
=
create
(
:geo_project_registry
,
project:
repository_state
.
project
)
registry
.
project
.
last_repository_updated_at
=
7
.
hours
.
ago
registry
.
project
.
repository_state
.
last_repository_verification_at
=
5
.
hours
.
ago
registry
.
last_repository_successful_sync_at
=
5
.
hours
.
ago
registry
.
project
.
repository_state
.
repository_verification_checksum
=
'my_checksum'
registry
end
let
(
:service
)
{
described_class
.
new
(
registry
,
:repository
)
}
it
'only works on the secondary'
do
stub_current_geo_node
(
primary
)
expect
(
service
).
not_to
receive
(
:log_info
)
service
.
execute
end
it
'sets checksum when the checksum matches'
do
allow
(
service
).
to
receive
(
:calculate_checksum
).
and_return
(
'my_checksum'
)
expect
(
service
).
to
receive
(
:record_status
).
once
.
with
(
checksum:
'my_checksum'
)
service
.
execute
end
it
'sets failure message when the checksum does not match'
do
allow
(
service
).
to
receive
(
:calculate_checksum
).
and_return
(
'not_my_checksum'
)
expect
(
service
).
to
receive
(
:record_status
).
once
.
with
(
error_msg:
start_with
(
'Repository checksum mismatch'
))
service
.
execute
end
end
shared_examples
'should_verify_checksum? for repositories/wikis'
do
|
type
|
let
(
:repository_state
)
{
create
(
:repository_state
,
project:
create
(
:project
,
:repository
))}
let
(
:registry
)
do
registry
=
create
(
:geo_project_registry
,
project:
repository_state
.
project
)
registry
.
project
.
last_repository_updated_at
=
7
.
hours
.
ago
registry
.
project
.
repository_state
.
public_send
(
"last_
#{
type
}
_verification_at="
,
5
.
hours
.
ago
)
registry
.
public_send
(
"last_
#{
type
}
_successful_sync_at="
,
5
.
hours
.
ago
)
registry
.
project
.
repository_state
.
public_send
(
"
#{
type
}
_verification_checksum="
,
'my_checksum'
)
registry
end
let
(
:service
)
{
described_class
.
new
(
registry
,
type
)
}
it
'verifies the repository'
do
expect
(
service
.
should_verify_checksum?
).
to
be_truthy
end
it
'does not verify if primary was never verified'
do
registry
.
project
.
repository_state
.
public_send
(
"last_
#{
type
}
_verification_at="
,
nil
)
expect
(
service
.
should_verify_checksum?
).
to
be_falsy
end
it
'does not verify if the checksums already match'
do
registry
.
project
.
repository_state
.
public_send
(
"
#{
type
}
_verification_checksum="
,
'my_checksum'
)
registry
.
public_send
(
"
#{
type
}
_verification_checksum="
,
'my_checksum'
)
expect
(
service
.
should_verify_checksum?
).
to
be_falsy
end
it
'does not verify if the primary was verified before the secondary'
do
registry
.
project
.
repository_state
.
public_send
(
"last_
#{
type
}
_verification_at="
,
50
.
minutes
.
ago
)
registry
.
public_send
(
"last_
#{
type
}
_verification_at="
,
30
.
minutes
.
ago
)
expect
(
service
.
should_verify_checksum?
).
to
be_falsy
end
it
'does verify if the secondary was never verified'
do
registry
.
public_send
(
"last_
#{
type
}
_verification_at="
,
nil
)
expect
(
service
.
should_verify_checksum?
).
to
be_truthy
end
it
'does not verify if never synced'
do
registry
.
public_send
(
"last_
#{
type
}
_successful_sync_at="
,
nil
)
expect
(
service
.
should_verify_checksum?
).
to
be_falsy
end
it
'does not verify if the secondary synced before the last secondary verification'
do
registry
.
public_send
(
"last_
#{
type
}
_verification_at="
,
50
.
minutes
.
ago
)
registry
.
public_send
(
"last_
#{
type
}
_successful_sync_at="
,
30
.
minutes
.
ago
)
expect
(
service
.
should_verify_checksum?
).
to
be_falsy
end
it
'has been at least 6 hours since the primary repository was updated'
do
registry
.
project
.
last_repository_updated_at
=
7
.
hours
.
ago
expect
(
service
.
should_verify_checksum?
).
to
be_truthy
end
end
describe
'#should_verify_checksum?'
do
context
'repository'
do
include_examples
'should_verify_checksum? for repositories/wikis'
,
:repository
end
context
'wiki'
do
include_examples
'should_verify_checksum? for repositories/wikis'
,
:wiki
end
end
shared_examples
'record_status for repositories/wikis'
do
|
type
|
it
'records a successful verification'
do
service
.
send
(
:record_status
,
checksum:
'my_checksum'
)
registry
.
reload
expect
(
registry
.
public_send
(
"
#{
type
}
_verification_checksum"
)).
to
eq
'my_checksum'
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_at"
)).
not_to
be_nil
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_failure"
)).
to
be_nil
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_failed"
)).
to
be_falsey
end
it
'records a failure'
do
service
.
send
(
:record_status
,
error_msg:
'Repository checksum did not match'
)
registry
.
reload
expect
(
registry
.
public_send
(
"
#{
type
}
_verification_checksum"
)).
to
be_nil
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_at"
)).
not_to
be_nil
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_failure"
)).
to
eq
'Repository checksum did not match'
expect
(
registry
.
public_send
(
"last_
#{
type
}
_verification_failed"
)).
to
be_truthy
end
end
describe
'#record_status'
do
let
(
:registry
)
{
create
(
:geo_project_registry
)
}
context
'for a repository'
do
let
(
:service
)
{
described_class
.
new
(
registry
,
:repository
)
}
include_examples
'record_status for repositories/wikis'
,
:repository
end
context
'for a wiki'
do
let
(
:service
)
{
described_class
.
new
(
registry
,
:wiki
)
}
include_examples
'record_status for repositories/wikis'
,
:wiki
end
end
end
lib/gitlab/import_export/import_export.yml
View file @
a8e34125
...
@@ -65,6 +65,7 @@ project_tree:
...
@@ -65,6 +65,7 @@ project_tree:
-
:create_access_levels
-
:create_access_levels
-
:project_feature
-
:project_feature
-
:custom_attributes
-
:custom_attributes
-
:prometheus_metrics
-
:project_badges
-
:project_badges
# Only include the following attributes for the models specified.
# Only include the following attributes for the models specified.
...
...
lib/gitlab/prometheus/metric_group.rb
View file @
a8e34125
...
@@ -10,9 +10,14 @@ module Gitlab
...
@@ -10,9 +10,14 @@ module Gitlab
AdditionalMetricsParser
.
load_groups_from_yaml
AdditionalMetricsParser
.
load_groups_from_yaml
end
end
# EE only
def
self
.
for_project
(
project
)
def
self
.
for_project
(
_
)
common_metrics
+
custom_metrics
(
project
)
common_metrics
end
def
self
.
custom_metrics
(
project
)
project
.
prometheus_metrics
.
all
.
group_by
(
&
:group_title
).
map
do
|
name
,
metrics
|
MetricGroup
.
new
(
name:
name
,
priority:
0
,
metrics:
metrics
.
map
(
&
:to_query_metric
))
end
end
end
end
end
end
end
...
...
locale/gitlab.pot
View file @
a8e34125
...
@@ -8,8 +8,13 @@ msgid ""
...
@@ -8,8 +8,13 @@ msgid ""
msgstr ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"Report-Msgid-Bugs-To: \n"
<<<<<<< HEAD
"POT-Creation-Date: 2018-03-08 08:54+0100\n"
"POT-Creation-Date: 2018-03-08 08:54+0100\n"
"PO-Revision-Date: 2018-03-08 08:54+0100\n"
"PO-Revision-Date: 2018-03-08 08:54+0100\n"
=======
"POT-Creation-Date: 2018-03-08 00:12+0100\n"
"PO-Revision-Date: 2018-03-08 00:12+0100\n"
>>>>>>> master
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"Language: \n"
...
@@ -3112,6 +3117,15 @@ msgstr ""
...
@@ -3112,6 +3117,15 @@ msgstr ""
msgid "Promote to Group Milestone"
msgid "Promote to Group Milestone"
msgstr ""
msgstr ""
msgid "Promote"
msgstr ""
msgid "Promote to Group Label"
msgstr ""
msgid "Promote to Group Milestone"
msgstr ""
msgid "Protip:"
msgid "Protip:"
msgstr ""
msgstr ""
...
...
spec/features/projects/merge_requests/user_creates_merge_request_spec.rb
View file @
a8e34125
...
@@ -8,13 +8,15 @@ describe 'User creates a merge request', :js do
...
@@ -8,13 +8,15 @@ describe 'User creates a merge request', :js do
merge_requests_template:
'This merge request should contain the following.'
)
merge_requests_template:
'This merge request should contain the following.'
)
end
end
let
(
:user
)
{
create
(
:user
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:approver
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
let
(
:user2
)
{
create
(
:user
)
}
before
do
before
do
project
.
add_master
(
user
)
project
.
add_master
(
user
)
project
.
add_master
(
approver
)
sign_in
(
user
)
sign_in
(
user
)
project
.
approvers
.
create
(
user_id:
us
er
.
id
)
project
.
approvers
.
create
(
user_id:
approv
er
.
id
)
visit
(
project_new_merge_request_path
(
project
))
visit
(
project_new_merge_request_path
(
project
))
end
end
...
@@ -34,7 +36,7 @@ describe 'User creates a merge request', :js do
...
@@ -34,7 +36,7 @@ describe 'User creates a merge request', :js do
# Approvers
# Approvers
page
.
within
(
'ul .unsaved-approvers'
)
do
page
.
within
(
'ul .unsaved-approvers'
)
do
expect
(
page
).
to
have_content
(
us
er
.
name
)
expect
(
page
).
to
have_content
(
approv
er
.
name
)
end
end
page
.
within
(
'.suggested-approvers'
)
do
page
.
within
(
'.suggested-approvers'
)
do
...
...
spec/javascripts/geo_nodes/mock_data.js
View file @
a8e34125
...
@@ -80,6 +80,12 @@ export const rawMockNodeDetails = {
...
@@ -80,6 +80,12 @@ export const rawMockNodeDetails = {
wikis_failed_count
:
0
,
wikis_failed_count
:
0
,
wikis_synced_count
:
12
,
wikis_synced_count
:
12
,
wikis_synced_in_percentage
:
'
100.00%
'
,
wikis_synced_in_percentage
:
'
100.00%
'
,
repositories_verification_failed_count
:
0
,
repositories_verified_count
:
12
,
repositories_verified_in_percentage
:
'
100.00%
'
,
wikis_verification_failed_count
:
0
,
wikis_verified_count
:
12
,
wikis_verified_in_percentage
:
'
100.00%
'
,
replication_slots_count
:
null
,
replication_slots_count
:
null
,
replication_slots_used_count
:
null
,
replication_slots_used_count
:
null
,
replication_slots_used_in_percentage
:
'
0.00%
'
,
replication_slots_used_in_percentage
:
'
0.00%
'
,
...
...
spec/javascripts/prometheus_metrics/ee/mock_data.js
0 → 100644
View file @
a8e34125
const
metrics
=
[
{
edit_path
:
'
/root/prometheus-test/prometheus/metrics/3/edit
'
,
id
:
3
,
title
:
'
Requests
'
,
group
:
'
Business
'
,
},
{
edit_path
:
'
/root/prometheus-test/prometheus/metrics/2/edit
'
,
id
:
2
,
title
:
'
Sales by the hour
'
,
group
:
'
Business
'
,
},
{
edit_path
:
'
/root/prometheus-test/prometheus/metrics/1/edit
'
,
id
:
1
,
title
:
'
Requests
'
,
group
:
'
Business
'
,
},
];
export
default
metrics
;
spec/javascripts/prometheus_metrics/ee/prometheus_metrics_spec.js
0 → 100644
View file @
a8e34125
import
MockAdapter
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
PrometheusMetrics
from
'
ee/prometheus_metrics/prometheus_metrics
'
;
import
PANEL_STATE
from
'
~/prometheus_metrics/constants
'
;
import
metrics
from
'
./mock_data
'
;
describe
(
'
PrometheusMetrics EE
'
,
()
=>
{
const
FIXTURE
=
'
services/prometheus/prometheus_service.html.raw
'
;
const
customMetricsEndpoint
=
'
http://test.host/frontend-fixtures/services-project/prometheus/metrics
'
;
let
mock
;
preloadFixtures
(
FIXTURE
);
beforeEach
(()
=>
{
mock
=
new
MockAdapter
(
axios
);
mock
.
onGet
(
customMetricsEndpoint
).
reply
(
200
,
{
metrics
,
});
loadFixtures
(
FIXTURE
);
});
afterEach
(()
=>
{
mock
.
restore
();
});
describe
(
'
Custom Metrics EE
'
,
()
=>
{
let
prometheusMetrics
;
beforeEach
(()
=>
{
prometheusMetrics
=
new
PrometheusMetrics
(
'
.js-prometheus-metrics-monitoring
'
);
});
it
(
'
should initialize wrapper element refs on the class object
'
,
()
=>
{
expect
(
prometheusMetrics
.
$wrapperCustomMetrics
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsPanel
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsCount
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsLoading
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsEmpty
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsList
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$newCustomMetricButton
).
not
.
toBeNull
();
expect
(
prometheusMetrics
.
$flashCustomMetricsContainer
).
not
.
toBeNull
();
});
it
(
'
should contain api endpoints
'
,
()
=>
{
expect
(
prometheusMetrics
.
activeCustomMetricsEndpoint
).
toEqual
(
customMetricsEndpoint
);
});
it
(
'
should show loading state when called with `loading`
'
,
()
=>
{
prometheusMetrics
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
LOADING
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsLoading
.
hasClass
(
'
hidden
'
)).
toEqual
(
false
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsEmpty
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsList
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
});
it
(
'
should show metrics list when called with `list`
'
,
()
=>
{
prometheusMetrics
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
LIST
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsLoading
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsEmpty
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsList
.
hasClass
(
'
hidden
'
)).
toEqual
(
false
);
});
it
(
'
should show empty state when called with `empty`
'
,
()
=>
{
prometheusMetrics
.
showMonitoringCustomMetricsPanelState
(
PANEL_STATE
.
EMPTY
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsLoading
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsEmpty
.
hasClass
(
'
hidden
'
)).
toEqual
(
false
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsList
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
});
it
(
'
should show monitored metrics list
'
,
()
=>
{
prometheusMetrics
.
customMetrics
=
metrics
;
prometheusMetrics
.
populateCustomMetrics
();
const
$metricsListLi
=
prometheusMetrics
.
$monitoredCustomMetricsList
.
find
(
'
li
'
);
expect
(
prometheusMetrics
.
$monitoredCustomMetricsLoading
.
hasClass
(
'
hidden
'
)).
toBeTruthy
();
expect
(
prometheusMetrics
.
$monitoredCustomMetricsList
.
hasClass
(
'
hidden
'
)).
toEqual
(
false
);
expect
(
$metricsListLi
.
length
).
toEqual
(
metrics
.
length
);
});
});
});
spec/lib/gitlab/import_export/all_models.yml
View file @
a8e34125
...
@@ -309,6 +309,7 @@ project:
...
@@ -309,6 +309,7 @@ project:
-
fork_network_member
-
fork_network_member
-
fork_network
-
fork_network
-
custom_attributes
-
custom_attributes
-
prometheus_metrics
-
lfs_file_locks
-
lfs_file_locks
-
project_badges
-
project_badges
-
source_of_merge_requests
-
source_of_merge_requests
...
@@ -317,6 +318,8 @@ award_emoji:
...
@@ -317,6 +318,8 @@ award_emoji:
-
user
-
user
priorities
:
priorities
:
-
label
-
label
prometheus_metrics
:
-
project
timelogs
:
timelogs
:
-
issue
-
issue
-
merge_request
-
merge_request
...
...
spec/lib/gitlab/import_export/safe_model_attributes.yml
View file @
a8e34125
...
@@ -553,6 +553,17 @@ ProjectCustomAttribute:
...
@@ -553,6 +553,17 @@ ProjectCustomAttribute:
-
project_id
-
project_id
-
key
-
key
-
value
-
value
PrometheusMetric
:
-
id
-
created_at
-
updated_at
-
project_id
-
y_label
-
unit
-
legend
-
title
-
query
-
group
LfsFileLock
:
LfsFileLock
:
-
id
-
id
-
path
-
path
...
...
spec/models/concerns/prometheus_adapter_spec.rb
View file @
a8e34125
...
@@ -75,6 +75,29 @@ describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
...
@@ -75,6 +75,29 @@ describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
end
end
end
end
end
end
describe
'validate_query'
do
let
(
:environment
)
{
build_stubbed
(
:environment
,
slug:
'env-slug'
)
}
let
(
:validation_query
)
{
Gitlab
::
Prometheus
::
Queries
::
ValidateQuery
.
name
}
let
(
:query
)
{
'avg(response)'
}
let
(
:validation_respone
)
{
{
data:
{
valid:
true
}
}
}
around
do
|
example
|
Timecop
.
freeze
{
example
.
run
}
end
context
'with valid data'
do
subject
{
service
.
query
(
:validate
,
query
)
}
before
do
stub_reactive_cache
(
service
,
validation_respone
,
validation_query
,
query
)
end
it
'returns query data'
do
is_expected
.
to
eq
(
query:
{
valid:
true
})
end
end
end
end
end
describe
'#calculate_reactive_cache'
do
describe
'#calculate_reactive_cache'
do
...
...
spec/serializers/pipeline_serializer_spec.rb
View file @
a8e34125
...
@@ -118,7 +118,7 @@ describe PipelineSerializer do
...
@@ -118,7 +118,7 @@ describe PipelineSerializer do
it
'verifies number of queries'
,
:request_store
do
it
'verifies number of queries'
,
:request_store
do
recorded
=
ActiveRecord
::
QueryRecorder
.
new
{
subject
}
recorded
=
ActiveRecord
::
QueryRecorder
.
new
{
subject
}
expect
(
recorded
.
count
).
to
be_within
(
1
).
of
(
40
)
expect
(
recorded
.
count
).
to
be_within
(
2
).
of
(
40
)
expect
(
recorded
.
cached_count
).
to
eq
(
0
)
expect
(
recorded
.
cached_count
).
to
eq
(
0
)
end
end
end
end
...
...
spec/support/prometheus/additional_metrics_shared_examples.rb
View file @
a8e34125
...
@@ -115,6 +115,50 @@ RSpec.shared_examples 'additional metrics query' do
...
@@ -115,6 +115,50 @@ RSpec.shared_examples 'additional metrics query' do
end
end
end
end
context
'with custom metrics'
do
let!
(
:metric
)
{
create
(
:prometheus_metric
,
project:
project
)
}
before
do
allow
(
client
).
to
receive
(
:query_range
).
with
(
'avg(metric)'
,
any_args
).
and_return
(
query_range_result
)
end
context
'without common metrics'
do
before
do
allow
(
metric_group_class
).
to
receive
(
:common_metrics
).
and_return
([])
end
it
'return group data for custom metric'
do
queries_with_result
=
{
queries:
[{
query_range:
'avg(metric)'
,
unit:
'm/s'
,
label:
'legend'
,
result:
query_range_result
}]
}
expect
(
query_result
).
to
match_schema
(
'prometheus/additional_metrics_query_result'
)
expect
(
query_result
.
count
).
to
eq
(
1
)
expect
(
query_result
.
first
[
:metrics
].
count
).
to
eq
(
1
)
expect
(
query_result
.
first
[
:metrics
].
first
).
to
include
(
queries_with_result
)
end
end
context
'with common metrics'
do
before
do
allow
(
client
).
to
receive
(
:query_range
).
with
(
'query_range_a'
,
any_args
).
and_return
(
query_range_result
)
allow
(
metric_group_class
).
to
receive
(
:common_metrics
).
and_return
([
simple_metric_group
(
metrics:
[
simple_metric
])])
end
it
'return group data for custom metric'
do
custom_queries_with_result
=
{
queries:
[{
query_range:
'avg(metric)'
,
unit:
'm/s'
,
label:
'legend'
,
result:
query_range_result
}]
}
common_queries_with_result
=
{
queries:
[{
query_range:
'query_range_a'
,
result:
query_range_result
}]
}
expect
(
query_result
).
to
match_schema
(
'prometheus/additional_metrics_query_result'
)
expect
(
query_result
.
count
).
to
eq
(
2
)
expect
(
query_result
).
to
all
(
satisfy
{
|
r
|
r
[
:metrics
].
count
==
1
})
expect
(
query_result
[
0
][
:metrics
].
first
).
to
include
(
common_queries_with_result
)
expect
(
query_result
[
1
][
:metrics
].
first
).
to
include
(
custom_queries_with_result
)
end
end
end
context
'with two groups with one metric each'
do
context
'with two groups with one metric each'
do
let
(
:metrics
)
{
[
simple_metric
(
queries:
[
simple_query
])]
}
let
(
:metrics
)
{
[
simple_metric
(
queries:
[
simple_query
])]
}
...
...
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