summaryrefslogtreecommitdiff
path: root/app/models/alert_management/alert.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/alert_management/alert.rb')
-rw-r--r--app/models/alert_management/alert.rb80
1 files changed, 56 insertions, 24 deletions
diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb
index e9b89af45c6..61cc15a522e 100644
--- a/app/models/alert_management/alert.rb
+++ b/app/models/alert_management/alert.rb
@@ -20,18 +20,7 @@ module AlertManagement
resolved: 2,
ignored: 3
}.freeze
-
- STATUS_EVENTS = {
- triggered: :trigger,
- acknowledged: :acknowledge,
- resolved: :resolve,
- ignored: :ignore
- }.freeze
-
- OPEN_STATUSES = [
- :triggered,
- :acknowledged
- ].freeze
+ private_constant :STATUSES
belongs_to :project
belongs_to :issue, optional: true
@@ -49,12 +38,16 @@ module AlertManagement
sha_attribute :fingerprint
+ TITLE_MAX_LENGTH = 200
+ DESCRIPTION_MAX_LENGTH = 1_000
+ SERVICE_MAX_LENGTH = 100
+ TOOL_MAX_LENGTH = 100
HOSTS_MAX_LENGTH = 255
- validates :title, length: { maximum: 200 }, presence: true
- validates :description, length: { maximum: 1_000 }
- validates :service, length: { maximum: 100 }
- validates :monitoring_tool, length: { maximum: 100 }
+ validates :title, length: { maximum: TITLE_MAX_LENGTH }, presence: true
+ validates :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
+ validates :service, length: { maximum: SERVICE_MAX_LENGTH }
+ validates :monitoring_tool, length: { maximum: TOOL_MAX_LENGTH }
validates :project, presence: true
validates :events, presence: true
validates :severity, presence: true
@@ -65,7 +58,7 @@ module AlertManagement
conditions: -> { not_resolved },
message: -> (object, data) { _('Cannot have multiple unresolved alerts') }
}, unless: :resolved?
- validate :hosts_length
+ validate :hosts_format
enum severity: {
critical: 0,
@@ -121,12 +114,13 @@ module AlertManagement
delegate :details_url, to: :present
scope :for_iid, -> (iid) { where(iid: iid) }
- scope :for_status, -> (status) { where(status: status) }
+ scope :for_status, -> (status) { with_status(status) }
scope :for_fingerprint, -> (project, fingerprint) { where(project: project, fingerprint: fingerprint) }
scope :for_environment, -> (environment) { where(environment: environment) }
+ scope :for_assignee_username, -> (assignee_username) { joins(:assignees).merge(User.by_username(assignee_username)) }
scope :search, -> (query) { fuzzy_search(query, [:title, :description, :monitoring_tool, :service]) }
- scope :open, -> { with_status(OPEN_STATUSES) }
- scope :not_resolved, -> { where.not(status: STATUSES[:resolved]) }
+ scope :open, -> { with_status(open_statuses) }
+ scope :not_resolved, -> { without_status(:resolved) }
scope :with_prometheus_alert, -> { includes(:prometheus_alert) }
scope :order_start_time, -> (sort_order) { order(started_at: sort_order) }
@@ -142,13 +136,33 @@ module AlertManagement
# Ascending sort order sorts statuses: Ignored > Resolved > Acknowledged > Triggered
# Descending sort order sorts statuses: Triggered > Acknowledged > Resolved > Ignored
# https://gitlab.com/gitlab-org/gitlab/-/issues/221242#what-is-the-expected-correct-behavior
- scope :order_status, -> (sort_order) { order(status: sort_order == :asc ? :desc : :asc) }
+ scope :order_status, -> (sort_order) { order(status: sort_order == :asc ? :desc : :asc) }
- scope :counts_by_status, -> { group(:status).count }
scope :counts_by_project_id, -> { group(:project_id).count }
alias_method :state, :status_name
+ def self.state_machine_statuses
+ @state_machine_statuses ||= state_machines[:status].states.to_h { |s| [s.name, s.value] }
+ end
+ private_class_method :state_machine_statuses
+
+ def self.status_value(name)
+ state_machine_statuses[name]
+ end
+
+ def self.status_name(raw_status)
+ state_machine_statuses.key(raw_status)
+ end
+
+ def self.counts_by_status
+ group(:status).count.transform_keys { |k| status_name(k) }
+ end
+
+ def self.status_names
+ @status_names ||= state_machine_statuses.keys
+ end
+
def self.sort_by_attribute(method)
case method.to_s
when 'started_at_asc' then order_start_time(:asc)
@@ -190,8 +204,25 @@ module AlertManagement
reference.to_i > 0 && reference.to_i <= Gitlab::Database::MAX_INT_VALUE
end
+ def self.open_statuses
+ [:triggered, :acknowledged]
+ end
+
+ def self.open_status?(status)
+ open_statuses.include?(status)
+ end
+
+ def status_event_for(status)
+ self.class.state_machines[:status].events.transitions_for(self, to: status.to_s.to_sym).first&.event
+ end
+
+ def change_status_to(new_status)
+ event = status_event_for(new_status)
+ event && fire_status_event(event)
+ end
+
def prometheus?
- monitoring_tool == Gitlab::AlertManagement::AlertParams::MONITORING_TOOLS[:prometheus]
+ monitoring_tool == Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
end
def register_new_event!
@@ -224,10 +255,11 @@ module AlertManagement
Gitlab::DataBuilder::Alert.build(self)
end
- def hosts_length
+ def hosts_format
return unless hosts
errors.add(:hosts, "hosts array is over #{HOSTS_MAX_LENGTH} chars") if hosts.join.length > HOSTS_MAX_LENGTH
+ errors.add(:hosts, "hosts array cannot be nested") if hosts.flatten != hosts
end
end
end