Commit 8c72b7b8 authored by Peter Leitzen's avatar Peter Leitzen

Merge branch 'map-prometheus-payload-severity' into 'master'

Map common severity values from a Prometheus alert payload

See merge request gitlab-org/gitlab!50871
parents 8a65ba1f 0f316dd2
---
title: Map common severity values from a Prometheus alert payload
merge_request: 50871
author:
type: added
......@@ -110,6 +110,14 @@ values extracted from the [`alerts` field in webhook payload](https://prometheus
- `full_query`: Alert query extracted from the payload's `generatorURL` field
- Optional list of attached annotations extracted from `annotations/*`
- Alert [GFM](../../user/markdown.md): GitLab Flavored Markdown from the payload's `annotations/gitlab_incident_markdown` field.
- Alert Severity (introduced in GitLab version [13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50871):
Extracted from the alert payload field `labels/severity`. Maps case-insensitive
value to [Alert's severity](../incident_management/alerts.md#alert-severity):
- **Critical**: `critical`, `s1`, `p1`, `emergency`, `fatal`, or any value not in this list
- **High**: `high`, `s2`, `p2`, `major`, `page`
- **Medium**: `medium`, `s3`, `p3`, `error`, `alert`
- **Low**: `low`, `s4`, `p4`, `warn`, `warning`
- **Info**: `info`, `s5`, `p5`, `debug`, `information`, `notice`
When GitLab receives a **Recovery Alert**, it closes the associated issue.
This action is recorded as a system message on the issue indicating that it
......
# frozen_string_literal: true
# Attribute mapping for alerts via prometheus alerting integration.
module Gitlab
module AlertManagement
module Payload
# Attribute mapping for alerts via prometheus alerting integration.
class Prometheus < Base
attribute :alert_markdown, paths: %w(annotations gitlab_incident_markdown)
attribute :annotations, paths: 'annotations'
......@@ -26,13 +26,49 @@ module Gitlab
paths: [%w(annotations title),
%w(annotations summary),
%w(labels alertname)]
attribute :starts_at_raw,
paths: [%w(startsAt)]
private :starts_at_raw
attribute :severity_raw, paths: %w(labels severity)
private :severity_raw
METRIC_TIME_WINDOW = 30.minutes
SEVERITY_MAP = {
'critical' => :critical,
'high' => :high,
'medium' => :medium,
'low' => :low,
'info' => :info,
's1' => :critical,
's2' => :high,
's3' => :medium,
's4' => :low,
's5' => :info,
'p1' => :critical,
'p2' => :high,
'p3' => :medium,
'p4' => :low,
'p5' => :info,
'debug' => :info,
'information' => :info,
'notice' => :info,
'warn' => :low,
'warning' => :low,
'minor' => :low,
'error' => :medium,
'major' => :high,
'emergency' => :critical,
'fatal' => :critical,
'alert' => :medium,
'page' => :high
}.freeze
# Handle an unmapped severity value the same way we treat missing values
# so we can fallback to alert's default severity `critical`.
UNMAPPED_SEVERITY = nil
def monitoring_tool
Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
end
......@@ -65,6 +101,12 @@ module Gitlab
project && title && starts_at_raw
end
def severity
return unless severity_raw
SEVERITY_MAP.fetch(severity_raw.to_s.downcase, UNMAPPED_SEVERITY)
end
private
def plain_gitlab_fingerprint
......
......@@ -156,8 +156,6 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
end
describe '#gitlab_fingerprint' do
subject { parsed_payload.gitlab_fingerprint }
let(:raw_payload) do
{
'startsAt' => Time.current.to_s,
......@@ -166,6 +164,8 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
}
end
subject { parsed_payload.gitlab_fingerprint }
it 'returns a fingerprint' do
plain_fingerprint = [
parsed_payload.send(:starts_at_raw),
......@@ -237,4 +237,65 @@ RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
it { is_expected.to be_falsey }
end
end
describe '#severity' do
using RSpec::Parameterized::TableSyntax
let(:raw_payload) { { 'labels' => { 'severity' => payload_severity } } }
subject { parsed_payload.severity }
context 'when set' do
where(:payload_severity, :expected_severity) do
'critical' | :critical
'high' | :high
'medium' | :medium
'low' | :low
'info' | :info
's1' | :critical
's2' | :high
's3' | :medium
's4' | :low
's5' | :info
'p1' | :critical
'p2' | :high
'p3' | :medium
'p4' | :low
'p5' | :info
'CRITICAL' | :critical
'cRiTiCaL' | :critical
'S1' | :critical
'unmapped' | nil
1 | nil
nil | nil
'debug' | :info
'information' | :info
'notice' | :info
'warn' | :low
'warning' | :low
'minor' | :low
'error' | :medium
'major' | :high
'emergency' | :critical
'fatal' | :critical
'alert' | :medium
'page' | :high
end
with_them do
it { is_expected.to eq(expected_severity) }
end
end
context 'without key' do
let(:raw_payload) { {} }
it { is_expected.to be_nil }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment