Commit 0a020f7a authored by James Lopez's avatar James Lopez

Merge branch '13402-close-alert-when-end-time-given' into 'master'

Resolve alert when end_time is given

Closes #217049 and #13402

See merge request gitlab-org/gitlab!41648
parents e0068324 6be508d0
...@@ -42,11 +42,37 @@ module Projects ...@@ -42,11 +42,37 @@ module Projects
end end
def process_existing_alert(alert) def process_existing_alert(alert)
alert.register_new_event! if am_alert_params[:ended_at].present?
process_resolved_alert(alert)
else
alert.register_new_event!
end
alert
end
def process_resolved_alert(alert)
return unless auto_close_incident?
if alert.resolve(am_alert_params[:ended_at])
close_issue(alert.issue)
end
alert
end
def close_issue(issue)
return if issue.blank? || issue.closed?
::Issues::CloseService
.new(project, User.alert_bot)
.execute(issue, system_note: false)
SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
end end
def create_alert def create_alert
alert = AlertManagement::Alert.create(am_alert_params) alert = AlertManagement::Alert.create(am_alert_params.except(:ended_at))
alert.execute_services if alert.persisted? alert.execute_services if alert.persisted?
SystemNoteService.create_new_alert(alert, 'Generic Alert Endpoint') SystemNoteService.create_new_alert(alert, 'Generic Alert Endpoint')
......
---
title: Automatically resolve alert when receiving end time
merge_request: 41648
author:
type: added
...@@ -43,6 +43,7 @@ You can customize the payload by sending the following parameters. All fields ot ...@@ -43,6 +43,7 @@ You can customize the payload by sending the following parameters. All fields ot
| `title` | String | The title of the incident. Required. | | `title` | String | The title of the incident. Required. |
| `description` | String | A high-level summary of the problem. | | `description` | String | A high-level summary of the problem. |
| `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue will be used. | | `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue will be used. |
| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. |
| `service` | String | The affected service. | | `service` | String | The affected service. |
| `monitoring_tool` | String | The name of the associated monitoring tool. | | `monitoring_tool` | String | The name of the associated monitoring tool. |
| `hosts` | String or Array | One or more hosts, as to where this incident occurred. | | `hosts` | String or Array | One or more hosts, as to where this incident occurred. |
......
...@@ -20,6 +20,7 @@ module Gitlab ...@@ -20,6 +20,7 @@ module Gitlab
hosts: Array(annotations[:hosts]), hosts: Array(annotations[:hosts]),
payload: payload, payload: payload,
started_at: parsed_payload['startsAt'], started_at: parsed_payload['startsAt'],
ended_at: parsed_payload['endsAt'],
severity: annotations[:severity], severity: annotations[:severity],
fingerprint: annotations[:fingerprint], fingerprint: annotations[:fingerprint],
environment: annotations[:environment] environment: annotations[:environment]
......
...@@ -20,7 +20,8 @@ module Gitlab ...@@ -20,7 +20,8 @@ module Gitlab
def call def call
{ {
'annotations' => annotations, 'annotations' => annotations,
'startsAt' => starts_at 'startsAt' => starts_at,
'endsAt' => ends_at
}.compact }.compact
end end
...@@ -74,6 +75,12 @@ module Gitlab ...@@ -74,6 +75,12 @@ module Gitlab
current_time current_time
end end
def ends_at
Time.parse(payload[:end_time].to_s).rfc3339
rescue ArgumentError
nil
end
def environment def environment
environment_name = payload[:gitlab_environment_name] environment_name = payload[:gitlab_environment_name]
...@@ -85,7 +92,7 @@ module Gitlab ...@@ -85,7 +92,7 @@ module Gitlab
end end
def secondary_params def secondary_params
payload.except(:start_time) payload.except(:start_time, :end_time)
end end
def flatten_secondary_params def flatten_secondary_params
......
...@@ -34,6 +34,7 @@ RSpec.describe Gitlab::AlertManagement::AlertParams do ...@@ -34,6 +34,7 @@ RSpec.describe Gitlab::AlertManagement::AlertParams do
hosts: ['gitlab.com'], hosts: ['gitlab.com'],
payload: payload, payload: payload,
started_at: started_at, started_at: started_at,
ended_at: nil,
fingerprint: nil, fingerprint: nil,
environment: nil environment: nil
) )
......
...@@ -7,10 +7,12 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do ...@@ -7,10 +7,12 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
describe '.call' do describe '.call' do
let(:starts_at) { Time.current.change(usec: 0) } let(:starts_at) { Time.current.change(usec: 0) }
let(:ends_at) { Time.current.change(usec: 0) }
let(:payload) do let(:payload) do
{ {
'title' => 'alert title', 'title' => 'alert title',
'start_time' => starts_at.rfc3339, 'start_time' => starts_at.rfc3339,
'end_time' => ends_at.rfc3339,
'description' => 'Description', 'description' => 'Description',
'monitoring_tool' => 'Monitoring tool name', 'monitoring_tool' => 'Monitoring tool name',
'service' => 'Service', 'service' => 'Service',
...@@ -32,7 +34,8 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do ...@@ -32,7 +34,8 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
'hosts' => ['gitlab.com'], 'hosts' => ['gitlab.com'],
'severity' => 'low' 'severity' => 'low'
}, },
'startsAt' => starts_at.rfc3339 'startsAt' => starts_at.rfc3339,
'endsAt' => ends_at.rfc3339
} }
) )
end end
...@@ -141,6 +144,7 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do ...@@ -141,6 +144,7 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
{ {
'title' => '', 'title' => '',
'start_time' => '', 'start_time' => '',
'end_time' => '',
'description' => '', 'description' => '',
'monitoring_tool' => '', 'monitoring_tool' => '',
'service' => '', 'service' => '',
......
...@@ -15,10 +15,12 @@ RSpec.describe Projects::Alerting::NotifyService do ...@@ -15,10 +15,12 @@ RSpec.describe Projects::Alerting::NotifyService do
let(:fingerprint) { 'testing' } let(:fingerprint) { 'testing' }
let(:service) { described_class.new(project, nil, payload) } let(:service) { described_class.new(project, nil, payload) }
let(:environment) { create(:environment, project: project) } let(:environment) { create(:environment, project: project) }
let(:ended_at) { nil }
let(:payload_raw) do let(:payload_raw) do
{ {
title: 'alert title', title: 'alert title',
start_time: starts_at.rfc3339, start_time: starts_at.rfc3339,
end_time: ended_at&.rfc3339,
severity: 'low', severity: 'low',
monitoring_tool: 'GitLab RSpec', monitoring_tool: 'GitLab RSpec',
service: 'GitLab Test Suite', service: 'GitLab Test Suite',
...@@ -38,9 +40,10 @@ RSpec.describe Projects::Alerting::NotifyService do ...@@ -38,9 +40,10 @@ RSpec.describe Projects::Alerting::NotifyService do
context 'with valid token' do context 'with valid token' do
let(:token) { alerts_service.token } let(:token) { alerts_service.token }
let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled) } let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled, auto_close_incident?: auto_close_enabled) }
let(:email_enabled) { false } let(:email_enabled) { false }
let(:issue_enabled) { false } let(:issue_enabled) { false }
let(:auto_close_enabled) { false }
before do before do
allow(service) allow(service)
...@@ -93,6 +96,57 @@ RSpec.describe Projects::Alerting::NotifyService do ...@@ -93,6 +96,57 @@ RSpec.describe Projects::Alerting::NotifyService do
it_behaves_like 'adds an alert management alert event' it_behaves_like 'adds an alert management alert event'
context 'end time given' do
let(:ended_at) { Time.current.change(nsec: 0) }
it 'does not resolve the alert' do
expect { subject }.not_to change { alert.reload.status }
end
it 'does not set the ended at' do
subject
expect(alert.reload.ended_at).to be_nil
end
it_behaves_like 'does not an create alert management alert'
context 'auto_close_enabled setting enabled' do
let(:auto_close_enabled) { true }
it 'resolves the alert and sets the end time', :aggregate_failures do
subject
alert.reload
expect(alert.resolved?).to eq(true)
expect(alert.ended_at).to eql(ended_at)
end
context 'related issue exists' do
let(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) }
let(:issue) { alert.issue }
context 'state_tracking is enabled' do
before do
stub_feature_flags(track_resource_state_change_events: true)
end
it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') }
it { expect { subject }.to change(ResourceStateEvent, :count).by(1) }
end
context 'state_tracking is disabled' do
before do
stub_feature_flags(track_resource_state_change_events: false)
end
it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') }
it { expect { subject }.to change(Note, :count).by(1) }
end
end
end
end
context 'existing alert is resolved' do context 'existing alert is resolved' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) } let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) }
...@@ -114,6 +168,13 @@ RSpec.describe Projects::Alerting::NotifyService do ...@@ -114,6 +168,13 @@ RSpec.describe Projects::Alerting::NotifyService do
end end
end end
context 'end time given' do
let(:ended_at) { Time.current }
it_behaves_like 'creates an alert management alert'
it_behaves_like 'assigns the alert properties'
end
context 'with a minimal payload' do context 'with a minimal payload' do
let(:payload_raw) do let(:payload_raw) do
{ {
......
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