FIX: Discard duplicate alert data before trying to insert to DB

FIX: Discard duplicate alert data before trying to insert to DB

This plugin considers alerts to be unique by external_url,alertname,id. Prometheus alertmanager considers alerts unique based on all their labels.

To avoid database errors when inserting, discard alerts which do not conform to the plugin’s definition of unique.

Long-term, we may want to adjust the plugin to fit prometheus’s definition

diff --git a/app/models/alert_receiver_alert.rb b/app/models/alert_receiver_alert.rb
index 869a5b9..5aa6711 100644
--- a/app/models/alert_receiver_alert.rb
+++ b/app/models/alert_receiver_alert.rb
@@ -112,6 +112,8 @@ class AlertReceiverAlert < ActiveRecord::Base
   end
 
   def self.update_alerts(alerts, mark_stale_external_url: nil)
+    alerts = alerts.uniq { |a| [a[:topic_id], a[:external_url], a[:identifier]] }
+
     groups = alerts.group_by { |a| a[:status] }
 
     topic_ids = self.update_firing(groups['firing'])
diff --git a/spec/model/alert_receiver_alert_spec.rb b/spec/model/alert_receiver_alert_spec.rb
index 2fb09fe..366b823 100644
--- a/spec/model/alert_receiver_alert_spec.rb
+++ b/spec/model/alert_receiver_alert_spec.rb
@@ -113,4 +113,16 @@ RSpec.describe 'alert_receiver_alert' do
     expect(AlertReceiverAlert.firing.count).to eq(3)
     expect(AlertReceiverAlert.stale.count).to eq(1)
   end
+
+  it "discards duplicate alerts before inserting" do
+    AlertReceiverAlert.update_alerts([
+      alert(identifier: 'myid1'),
+      alert(identifier: 'myid1'),
+      alert(identifier: 'myid2'),
+      alert(identifier: 'myid2')
+    ])
+
+    expect(AlertReceiverAlert.count).to eq(2)
+    expect(AlertReceiverAlert.firing.count).to eq(2)
+  end
 end

GitHub sha: 2c0a4b51

1 Like