diff options
Diffstat (limited to 'lib/gitlab/alerting')
-rw-r--r-- | lib/gitlab/alerting/alert.rb | 215 | ||||
-rw-r--r-- | lib/gitlab/alerting/alert_annotation.rb | 11 | ||||
-rw-r--r-- | lib/gitlab/alerting/notification_payload_parser.rb | 107 |
3 files changed, 0 insertions, 333 deletions
diff --git a/lib/gitlab/alerting/alert.rb b/lib/gitlab/alerting/alert.rb deleted file mode 100644 index 94b81b7d290..00000000000 --- a/lib/gitlab/alerting/alert.rb +++ /dev/null @@ -1,215 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Alerting - class Alert - include ActiveModel::Model - include Gitlab::Utils::StrongMemoize - include Presentable - - attr_accessor :project, :payload, :am_alert - - def self.for_alert_management_alert(project:, alert:) - params = if alert.prometheus? - alert.payload - else - Gitlab::Alerting::NotificationPayloadParser.call(alert.payload.to_h, alert.project) - end - - self.new(project: project, payload: params, am_alert: alert) - end - - def gitlab_alert - strong_memoize(:gitlab_alert) do - parse_gitlab_alert_from_payload - end - end - - def metric_id - strong_memoize(:metric_id) do - payload&.dig('labels', 'gitlab_alert_id') - 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 - end - end - - def description - strong_memoize(:description) do - parse_description_from_payload - end - end - - def environment - strong_memoize(:environment) do - gitlab_alert&.environment || parse_environment_from_payload - end - end - - def annotations - strong_memoize(:annotations) do - parse_annotations_from_payload || [] - end - end - - def starts_at - strong_memoize(:starts_at) do - parse_datetime_from_payload('startsAt') - end - end - - def starts_at_raw - strong_memoize(:starts_at_raw) do - payload&.dig('startsAt') - end - end - - def ends_at - strong_memoize(:ends_at) do - parse_datetime_from_payload('endsAt') - end - end - - def full_query - strong_memoize(:full_query) do - gitlab_alert&.full_query || parse_expr_from_payload - end - end - - def y_label - strong_memoize(:y_label) do - parse_y_label_from_payload || title - end - end - - def alert_markdown - strong_memoize(:alert_markdown) do - parse_alert_markdown_from_payload - end - end - - def status - strong_memoize(:status) do - payload&.dig('status') - end - end - - def firing? - status == 'firing' - end - - def resolved? - status == 'resolved' - end - - def gitlab_managed? - metric_id.present? - end - - def gitlab_fingerprint - Gitlab::AlertManagement::Fingerprint.generate(plain_gitlab_fingerprint) - end - - def valid? - payload.respond_to?(:dig) && project && title && starts_at - end - - def present - super(presenter_class: Projects::Prometheus::AlertPresenter) - end - - private - - def plain_gitlab_fingerprint - if gitlab_managed? - [metric_id, starts_at_raw].join('/') - else # self managed - [starts_at_raw, title, full_query].join('/') - end - end - - def parse_environment_from_payload - environment_name = payload&.dig('labels', 'gitlab_environment_name') - - return unless environment_name - - EnvironmentsFinder.new(project, nil, { name: environment_name }) - .find - &.first - end - - def parse_gitlab_alert_from_payload - 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, id: gitlab_prometheus_alert_id) - .execute - end - - def parse_title_from_payload - payload&.dig('annotations', 'title') || - payload&.dig('annotations', 'summary') || - payload&.dig('labels', 'alertname') - end - - def parse_description_from_payload - payload&.dig('annotations', 'description') - end - - def parse_annotations_from_payload - payload&.dig('annotations')&.map do |label, value| - Alerting::AlertAnnotation.new(label: label, value: value) - end - end - - def parse_datetime_from_payload(field) - value = payload&.dig(field) - return unless value - - # value is a rfc3339 timestamp - # Timestamps from Prometheus and Alertmanager are UTC RFC3339 timestamps like: '2018-03-12T09:06:00Z' (Z represents 0 offset or UTC) - # .utc sets the datetime zone to `UTC` - Time.rfc3339(value).utc - rescue ArgumentError - end - - # Parses `g0.expr` from `generatorURL`. - # - # Example: http://localhost:9090/graph?g0.expr=vector%281%29&g0.tab=1 - def parse_expr_from_payload - url = payload&.dig('generatorURL') - return unless url - - uri = URI(url) - - Rack::Utils.parse_query(uri.query).fetch('g0.expr') - rescue URI::InvalidURIError, KeyError - end - - def parse_alert_markdown_from_payload - payload&.dig('annotations', 'gitlab_incident_markdown') - end - - def parse_y_label_from_payload - payload&.dig('annotations', 'gitlab_y_label') - end - end - end -end diff --git a/lib/gitlab/alerting/alert_annotation.rb b/lib/gitlab/alerting/alert_annotation.rb deleted file mode 100644 index a4b3a97b08c..00000000000 --- a/lib/gitlab/alerting/alert_annotation.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Alerting - class AlertAnnotation - include ActiveModel::Model - - attr_accessor :label, :value - end - end -end diff --git a/lib/gitlab/alerting/notification_payload_parser.rb b/lib/gitlab/alerting/notification_payload_parser.rb deleted file mode 100644 index 348f851f551..00000000000 --- a/lib/gitlab/alerting/notification_payload_parser.rb +++ /dev/null @@ -1,107 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module Alerting - class NotificationPayloadParser - BadPayloadError = Class.new(StandardError) - - DEFAULT_TITLE = 'New: Incident' - DEFAULT_SEVERITY = 'critical' - - def initialize(payload, project) - @payload = payload.to_h.with_indifferent_access - @project = project - end - - def self.call(payload, project) - new(payload, project).call - end - - def call - { - 'annotations' => annotations, - 'startsAt' => starts_at, - 'endsAt' => ends_at - }.compact - end - - private - - attr_reader :payload, :project - - def title - payload[:title].presence || DEFAULT_TITLE - end - - def severity - payload[:severity].presence || DEFAULT_SEVERITY - end - - def fingerprint - Gitlab::AlertManagement::Fingerprint.generate(payload[:fingerprint]) - end - - def annotations - primary_params - .reverse_merge(flatten_secondary_params) - .transform_values(&:presence) - .compact - end - - def primary_params - { - 'title' => title, - 'description' => payload[:description], - 'monitoring_tool' => payload[:monitoring_tool], - 'service' => payload[:service], - 'hosts' => hosts.presence, - 'severity' => severity, - 'fingerprint' => fingerprint, - 'environment' => environment - } - end - - def hosts - Array(payload[:hosts]).reject(&:blank?) - end - - def current_time - Time.current.change(usec: 0).rfc3339 - end - - def starts_at - Time.parse(payload[:start_time].to_s).rfc3339 - rescue ArgumentError - current_time - end - - def ends_at - Time.parse(payload[:end_time].to_s).rfc3339 - rescue ArgumentError - nil - end - - def environment - environment_name = payload[:gitlab_environment_name] - - return unless environment_name - - EnvironmentsFinder.new(project, nil, { name: environment_name }) - .find - &.first - end - - def secondary_params - payload.except(:start_time, :end_time) - end - - def flatten_secondary_params - Gitlab::Utils::SafeInlineHash.merge_keys!(secondary_params) - rescue ArgumentError - raise BadPayloadError, 'The payload is too big' - end - end - end -end - -Gitlab::Alerting::NotificationPayloadParser.prepend_if_ee('EE::Gitlab::Alerting::NotificationPayloadParser') |