2020-04-08 11:09:29 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Prometheus
|
|
|
|
class CreateDefaultAlertsService < BaseService
|
|
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
|
|
|
|
attr_reader :project
|
|
|
|
|
|
|
|
DEFAULT_ALERTS = [
|
|
|
|
{
|
|
|
|
identifier: 'response_metrics_nginx_ingress_16_http_error_rate',
|
|
|
|
operator: 'gt',
|
|
|
|
threshold: 0.1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: 'response_metrics_nginx_ingress_http_error_rate',
|
|
|
|
operator: 'gt',
|
|
|
|
threshold: 0.1
|
2020-04-13 11:09:20 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
identifier: 'response_metrics_nginx_http_error_percentage',
|
|
|
|
operator: 'gt',
|
|
|
|
threshold: 0.1
|
2020-04-08 11:09:29 -04:00
|
|
|
}
|
|
|
|
].freeze
|
|
|
|
|
|
|
|
def initialize(project:)
|
|
|
|
@project = project
|
|
|
|
end
|
|
|
|
|
|
|
|
def execute
|
|
|
|
return ServiceResponse.error(message: 'Invalid project') unless project
|
|
|
|
return ServiceResponse.error(message: 'Invalid environment') unless environment
|
|
|
|
|
|
|
|
create_alerts
|
2020-06-10 02:08:18 -04:00
|
|
|
schedule_prometheus_update
|
2020-04-08 11:09:29 -04:00
|
|
|
|
|
|
|
ServiceResponse.success
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def create_alerts
|
|
|
|
DEFAULT_ALERTS.each do |alert_hash|
|
|
|
|
identifier = alert_hash[:identifier]
|
|
|
|
next if alerts_by_identifier(environment).key?(identifier)
|
|
|
|
|
|
|
|
metric = metrics_by_identifier[identifier]
|
|
|
|
next unless metric
|
|
|
|
|
|
|
|
create_alert(alert: alert_hash, metric: metric)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-06-10 02:08:18 -04:00
|
|
|
def schedule_prometheus_update
|
|
|
|
return unless prometheus_application
|
|
|
|
|
|
|
|
::Clusters::Applications::ScheduleUpdateService.new(prometheus_application, project).execute
|
|
|
|
end
|
|
|
|
|
|
|
|
def prometheus_application
|
|
|
|
environment.cluster_prometheus_adapter
|
|
|
|
end
|
|
|
|
|
2020-04-08 11:09:29 -04:00
|
|
|
def metrics_by_identifier
|
|
|
|
strong_memoize(:metrics_by_identifier) do
|
|
|
|
metric_identifiers = DEFAULT_ALERTS.map { |alert| alert[:identifier] }
|
|
|
|
|
|
|
|
PrometheusMetricsFinder
|
|
|
|
.new(identifier: metric_identifiers, common: true)
|
|
|
|
.execute
|
|
|
|
.index_by(&:identifier)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def alerts_by_identifier(environment)
|
|
|
|
strong_memoize(:alerts_by_identifier) do
|
|
|
|
Projects::Prometheus::AlertsFinder
|
|
|
|
.new(project: project, metric: metrics_by_identifier.values, environment: environment)
|
|
|
|
.execute
|
|
|
|
.index_by { |alert| alert.prometheus_metric.identifier }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def environment
|
|
|
|
strong_memoize(:environment) do
|
|
|
|
EnvironmentsFinder.new(project, nil, name: 'production').find.first ||
|
|
|
|
project.environments.first
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_alert(alert:, metric:)
|
|
|
|
PrometheusAlert.create!(
|
|
|
|
project: project,
|
|
|
|
prometheus_metric: metric,
|
|
|
|
environment: environment,
|
|
|
|
threshold: alert[:threshold],
|
|
|
|
operator: alert[:operator]
|
|
|
|
)
|
|
|
|
rescue ActiveRecord::RecordNotUnique
|
|
|
|
# Ignore duplicate creations although it unlikely to happen
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|