Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
de2fb5b82c
commit
ed5add1c2f
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module Metrics
|
||||
class DashboardResolver < Resolvers::BaseResolver
|
||||
argument :path, GraphQL::STRING_TYPE,
|
||||
required: true,
|
||||
description: "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'"
|
||||
|
||||
type Types::Metrics::DashboardType, null: true
|
||||
|
||||
alias_method :environment, :object
|
||||
|
||||
def resolve(**args)
|
||||
return unless environment
|
||||
|
||||
::PerformanceMonitoring::PrometheusDashboard.find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -15,5 +15,9 @@ module Types
|
|||
|
||||
field :state, GraphQL::STRING_TYPE, null: false,
|
||||
description: 'State of the environment, for example: available/stopped'
|
||||
|
||||
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
|
||||
description: 'Metrics dashboard schema for the environment',
|
||||
resolver: Resolvers::Metrics::DashboardResolver
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module Metrics
|
||||
# rubocop: disable Graphql/AuthorizeTypes
|
||||
# Authorization is performed at environment level
|
||||
class DashboardType < ::Types::BaseObject
|
||||
graphql_name 'MetricsDashboard'
|
||||
|
||||
field :path, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'Path to a file with the dashboard definition'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
end
|
|
@ -4,27 +4,41 @@ module PerformanceMonitoring
|
|||
class PrometheusDashboard
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :dashboard, :panel_groups
|
||||
attr_accessor :dashboard, :panel_groups, :path, :environment, :priority
|
||||
|
||||
validates :dashboard, presence: true
|
||||
validates :panel_groups, presence: true
|
||||
|
||||
def self.from_json(json_content)
|
||||
dashboard = new(
|
||||
dashboard: json_content['dashboard'],
|
||||
panel_groups: json_content['panel_groups'].map { |group| PrometheusPanelGroup.from_json(group) }
|
||||
)
|
||||
class << self
|
||||
def from_json(json_content)
|
||||
dashboard = new(
|
||||
dashboard: json_content['dashboard'],
|
||||
panel_groups: json_content['panel_groups'].map { |group| PrometheusPanelGroup.from_json(group) }
|
||||
)
|
||||
|
||||
dashboard.tap(&:validate!)
|
||||
dashboard.tap(&:validate!)
|
||||
end
|
||||
|
||||
def find_for(project:, user:, path:, options: {})
|
||||
dashboard_response = Gitlab::Metrics::Dashboard::Finder.find(project, user, options.merge(dashboard_path: path))
|
||||
return unless dashboard_response[:status] == :success
|
||||
|
||||
new(
|
||||
{
|
||||
path: path,
|
||||
environment: options[:environment]
|
||||
}.merge(dashboard_response[:dashboard])
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def to_yaml
|
||||
self.as_json(only: valid_attributes).to_yaml
|
||||
self.as_json(only: yaml_valid_attributes).to_yaml
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_attributes
|
||||
def yaml_valid_attributes
|
||||
%w(panel_groups panels metrics group priority type title y_label weight id unit label query query_range dashboard)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,7 +56,8 @@ class PrometheusAlert < ApplicationRecord
|
|||
"for" => "5m",
|
||||
"labels" => {
|
||||
"gitlab" => "hook",
|
||||
"gitlab_alert_id" => prometheus_metric_id
|
||||
"gitlab_alert_id" => prometheus_metric_id,
|
||||
"gitlab_prometheus_alert_id" => id
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Prevent wrong environment being used when processing Prometheus alert
|
||||
merge_request: 29119
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Exclude 'trial_ends_on', 'shared_runners_minutes_limit' & 'extra_shared_runners_minutes_limit' from list of exported Group attributes
|
||||
merge_request: 29259
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add graphQL interface to fetch metrics dashboard
|
||||
merge_request: 29112
|
||||
author:
|
||||
type: added
|
|
@ -178,6 +178,18 @@ Plan.default.limits.update!(ci_pipeline_schedules: 100)
|
|||
|
||||
## Instance monitoring and metrics
|
||||
|
||||
### Incident Management inbound alert limits
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14932) in GitLab 12.5.
|
||||
|
||||
Limiting inbound alerts for an incident reduces the number of alerts (issues)
|
||||
that can be created within a period of time, which can help prevent overloading
|
||||
your incident responders with duplicate issues. You can reduce the volume of
|
||||
alerts in the following ways:
|
||||
|
||||
- Max requests per period per project, 3600 seconds by default.
|
||||
- Rate limit period in seconds, 3600 seconds by default.
|
||||
|
||||
### Prometheus Alert JSON payloads
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14929) in GitLab 12.6.
|
||||
|
|
|
@ -1882,6 +1882,16 @@ type Environment {
|
|||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Metrics dashboard schema for the environment
|
||||
"""
|
||||
metricsDashboard(
|
||||
"""
|
||||
Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'
|
||||
"""
|
||||
path: String!
|
||||
): MetricsDashboard
|
||||
|
||||
"""
|
||||
Human-readable name of the environment
|
||||
"""
|
||||
|
@ -5278,6 +5288,13 @@ type Metadata {
|
|||
version: String!
|
||||
}
|
||||
|
||||
type MetricsDashboard {
|
||||
"""
|
||||
Path to a file with the dashboard definition
|
||||
"""
|
||||
path: String
|
||||
}
|
||||
|
||||
"""
|
||||
Represents a milestone.
|
||||
"""
|
||||
|
|
|
@ -5580,6 +5580,33 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "metricsDashboard",
|
||||
"description": "Metrics dashboard schema for the environment",
|
||||
"args": [
|
||||
{
|
||||
"name": "path",
|
||||
"description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "MetricsDashboard",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Human-readable name of the environment",
|
||||
|
@ -15117,6 +15144,33 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "MetricsDashboard",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
"name": "path",
|
||||
"description": "Path to a file with the dashboard definition",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Milestone",
|
||||
|
|
|
@ -324,6 +324,7 @@ Describes where code is deployed for a project
|
|||
| Name | Type | Description |
|
||||
| --- | ---- | ---------- |
|
||||
| `id` | ID! | ID of the environment |
|
||||
| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment |
|
||||
| `name` | String! | Human-readable name of the environment |
|
||||
| `state` | String! | State of the environment, for example: available/stopped |
|
||||
|
||||
|
@ -815,6 +816,12 @@ Autogenerated return type of MergeRequestSetWip
|
|||
| `revision` | String! | Revision |
|
||||
| `version` | String! | Version |
|
||||
|
||||
## MetricsDashboard
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | ---- | ---------- |
|
||||
| `path` | String | Path to a file with the dashboard definition |
|
||||
|
||||
## Milestone
|
||||
|
||||
Represents a milestone.
|
||||
|
|
|
@ -721,7 +721,7 @@ For example, in order to test new index you can do the following:
|
|||
Create the index:
|
||||
|
||||
```sql
|
||||
exec CREATE INDEX index_projects_marked_for_deletion ON projects (marked_for_deletion_at) WHERE marked_for_deletion_at IS NOT NULL
|
||||
exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL
|
||||
```
|
||||
|
||||
Analyze the table to update its statistics:
|
||||
|
@ -733,7 +733,7 @@ exec ANALYZE projects
|
|||
Get the query plan:
|
||||
|
||||
```sql
|
||||
explain SELECT * FROM projects WHERE marked_for_deletion_at < CURRENT_DATE
|
||||
explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE
|
||||
```
|
||||
|
||||
Once done you can rollback your changes:
|
||||
|
|
|
@ -309,6 +309,7 @@ The following tables outline the details of expected properties.
|
|||
| `label` | string | no, but highly encouraged | Defines the legend-label for the query. Should be unique within the panel's metrics. Can contain time series labels as interpolated variables. |
|
||||
| `query` | string | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `query_range` | string | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `step` | number | no, value is calculated if not defined | Defines query resolution step width in float number of seconds. Metrics on the same panel should use the same `step` value. |
|
||||
|
||||
##### Dynamic labels
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def gitlab_prometheus_alert_id
|
||||
strong_memoize(:gitlab_prometheus_alert_id) do
|
||||
payload&.dig('labels', 'gitlab_prometheus_alert_id')
|
||||
end
|
||||
end
|
||||
|
||||
def title
|
||||
strong_memoize(:title) do
|
||||
gitlab_alert&.title || parse_title_from_payload
|
||||
|
@ -120,12 +126,19 @@ module Gitlab
|
|||
end
|
||||
|
||||
def parse_gitlab_alert_from_payload
|
||||
return unless metric_id
|
||||
alerts_found = matching_gitlab_alerts
|
||||
|
||||
return if alerts_found.blank? || alerts_found.size > 1
|
||||
|
||||
alerts_found.first
|
||||
end
|
||||
|
||||
def matching_gitlab_alerts
|
||||
return unless metric_id || gitlab_prometheus_alert_id
|
||||
|
||||
Projects::Prometheus::AlertsFinder
|
||||
.new(project: project, metric: metric_id)
|
||||
.new(project: project, metric: metric_id, id: gitlab_prometheus_alert_id)
|
||||
.execute
|
||||
.first
|
||||
end
|
||||
|
||||
def parse_title_from_payload
|
||||
|
|
|
@ -14,7 +14,7 @@ module Gitlab
|
|||
|
||||
define_histogram :gitlab_redis_diff_caching_memory_usage_bytes do
|
||||
docstring 'Redis diff caching memory usage by key'
|
||||
buckets [100, 1000, 10000, 100000, 1000000, 10000000]
|
||||
buckets [100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000]
|
||||
end
|
||||
|
||||
define_counter :gitlab_redis_diff_caching_hit do
|
||||
|
|
|
@ -36,6 +36,9 @@ excluded_attributes:
|
|||
- :runners_token_encrypted
|
||||
- :saml_discovery_token
|
||||
- :visibility_level
|
||||
- :trial_ends_on
|
||||
- :shared_runners_minute_limit
|
||||
- :extra_shared_runners_minutes_limit
|
||||
epics:
|
||||
- :state_id
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -19,18 +19,15 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 7,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"saml_discovery_token": "rBKx3ioz",
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"runners_token": "token",
|
||||
|
@ -1075,18 +1072,15 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 4351,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"saml_discovery_token": "ki3Xnjw3",
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -1649,18 +1643,15 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 4351,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"saml_discovery_token": "m7cx4AZi",
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
|
|
@ -19,18 +19,15 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": null,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"saml_discovery_token": "rBKx3ioz",
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
|
|
@ -20,17 +20,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": null,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -61,17 +58,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -102,17 +96,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -143,17 +134,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
|
|
@ -20,17 +20,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": null,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -61,17 +58,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -102,17 +96,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -143,17 +134,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
|
|
@ -20,17 +20,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": null,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -61,17 +58,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -102,17 +96,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
@ -143,17 +134,14 @@
|
|||
"ldap_sync_last_sync_at": null,
|
||||
"lfs_enabled": null,
|
||||
"parent_id": 283,
|
||||
"shared_runners_minutes_limit": null,
|
||||
"repository_size_limit": null,
|
||||
"require_two_factor_authentication": false,
|
||||
"two_factor_grace_period": 48,
|
||||
"plan_id": null,
|
||||
"project_creation_level": 2,
|
||||
"trial_ends_on": null,
|
||||
"file_template_project_id": null,
|
||||
"custom_project_templates_group_id": null,
|
||||
"auto_devops_enabled": null,
|
||||
"extra_shared_runners_minutes_limit": null,
|
||||
"last_ci_minutes_notification_at": null,
|
||||
"last_ci_minutes_usage_notification_level": null,
|
||||
"subgroup_creation_level": 1,
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Resolvers::Metrics::DashboardResolver do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
describe '#resolve' do
|
||||
subject(:resolve_dashboard) { resolve(described_class, obj: parent_object, args: args, ctx: { current_user: current_user }) }
|
||||
|
||||
let(:args) do
|
||||
{
|
||||
path: 'config/prometheus/common_metrics.yml'
|
||||
}
|
||||
end
|
||||
|
||||
context 'for environment' do
|
||||
let(:project) { create(:project) }
|
||||
let(:parent_object) { create(:environment, project: project) }
|
||||
|
||||
before do
|
||||
project.add_developer(current_user)
|
||||
end
|
||||
|
||||
it 'use ActiveModel class to find matching dashboard', :aggregate_failures do
|
||||
expected_arguments = { project: project, user: current_user, path: args[:path], options: { environment: parent_object } }
|
||||
|
||||
expect(PerformanceMonitoring::PrometheusDashboard).to receive(:find_for).with(expected_arguments).and_return(PerformanceMonitoring::PrometheusDashboard.new)
|
||||
expect(resolve_dashboard).to be_instance_of PerformanceMonitoring::PrometheusDashboard
|
||||
end
|
||||
|
||||
context 'without parent object' do
|
||||
let(:parent_object) { nil }
|
||||
|
||||
it 'returns nil', :aggregate_failures do
|
||||
expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:find_for)
|
||||
expect(resolve_dashboard).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ describe GitlabSchema.types['Environment'] do
|
|||
|
||||
it 'has the expected fields' do
|
||||
expected_fields = %w[
|
||||
name id state
|
||||
name id state metrics_dashboard
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe GitlabSchema.types['MetricsDashboard'] do
|
||||
it { expect(described_class.graphql_name).to eq('MetricsDashboard') }
|
||||
|
||||
it 'has the expected fields' do
|
||||
expected_fields = %w[
|
||||
path
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
|
@ -9,11 +9,14 @@ describe Gitlab::Alerting::Alert do
|
|||
let(:payload) { {} }
|
||||
|
||||
shared_context 'gitlab alert' do
|
||||
let(:gitlab_alert_id) { gitlab_alert.prometheus_metric_id.to_s }
|
||||
let!(:gitlab_alert) { create(:prometheus_alert, project: project) }
|
||||
let(:gitlab_alert_id) { gitlab_alert.id }
|
||||
|
||||
before do
|
||||
payload['labels'] = { 'gitlab_alert_id' => gitlab_alert_id }
|
||||
payload['labels'] = {
|
||||
'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s,
|
||||
'gitlab_prometheus_alert_id' => gitlab_alert_id
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -68,6 +71,41 @@ describe Gitlab::Alerting::Alert do
|
|||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when two alerts with the same metric exist' do
|
||||
include_context 'gitlab alert'
|
||||
|
||||
let!(:second_gitlab_alert) do
|
||||
create(:prometheus_alert,
|
||||
project: project,
|
||||
prometheus_metric_id: gitlab_alert.prometheus_metric_id
|
||||
)
|
||||
end
|
||||
|
||||
context 'alert id given in params' do
|
||||
before do
|
||||
payload['labels'] = {
|
||||
'gitlab_alert_id' => gitlab_alert.prometheus_metric_id.to_s,
|
||||
'gitlab_prometheus_alert_id' => second_gitlab_alert.id
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to eq(second_gitlab_alert) }
|
||||
end
|
||||
|
||||
context 'metric id given in params' do
|
||||
# This tests the case when two alerts are found, as metric id
|
||||
# is not unique.
|
||||
|
||||
# Note the metric id was incorrectly named as 'gitlab_alert_id'
|
||||
# in PrometheusAlert#to_param.
|
||||
before do
|
||||
payload['labels'] = { 'gitlab_alert_id' => gitlab_alert.prometheus_metric_id }
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#title' do
|
||||
|
|
|
@ -96,7 +96,8 @@ describe PrometheusAlert do
|
|||
"for" => "5m",
|
||||
"labels" => {
|
||||
"gitlab" => "hook",
|
||||
"gitlab_alert_id" => metric.id
|
||||
"gitlab_alert_id" => metric.id,
|
||||
"gitlab_prometheus_alert_id" => subject.id
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'Getting Metrics Dashboard' do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let(:project) { create(:project) }
|
||||
let!(:environment) { create(:environment, project: project) }
|
||||
|
||||
let(:fields) do
|
||||
<<~QUERY
|
||||
#{all_graphql_fields_for('MetricsDashboard'.classify)}
|
||||
QUERY
|
||||
end
|
||||
|
||||
let(:query) do
|
||||
%(
|
||||
query {
|
||||
project(fullPath:"#{project.full_path}") {
|
||||
environments(name: "#{environment.name}") {
|
||||
nodes {
|
||||
metricsDashboard(path: "#{path}"){
|
||||
#{fields}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
context 'for anonymous user' do
|
||||
before do
|
||||
post_graphql(query, current_user: current_user)
|
||||
end
|
||||
|
||||
context 'requested dashboard is available' do
|
||||
let(:path) { 'config/prometheus/common_metrics.yml' }
|
||||
|
||||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it 'returns nil' do
|
||||
dashboard = graphql_data.dig('project', 'environments', 'nodes')
|
||||
|
||||
expect(dashboard).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for user with developer access' do
|
||||
before do
|
||||
project.add_developer(current_user)
|
||||
post_graphql(query, current_user: current_user)
|
||||
end
|
||||
|
||||
context 'requested dashboard is available' do
|
||||
let(:path) { 'config/prometheus/common_metrics.yml' }
|
||||
|
||||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it 'returns metrics dashboard' do
|
||||
dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
|
||||
|
||||
expect(dashboard).to eql("path" => path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'requested dashboard can not be found' do
|
||||
let(:path) { 'config/prometheus/i_am_not_here.yml' }
|
||||
|
||||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it 'return snil' do
|
||||
dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
|
||||
|
||||
expect(dashboard).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue