diff --git a/app/models/blazer/check.rb b/app/models/blazer/check.rb index 5f14ecad2..6a796a2a2 100644 --- a/app/models/blazer/check.rb +++ b/app/models/blazer/check.rb @@ -49,7 +49,7 @@ def update_state(result) "passing" end elsif result.rows.any? - check_type == "missing_data" ? "passing" : "failing" + %w[bad_data new_bad_data].include?(check_type) ? 'failing' : 'passing' else check_type == "missing_data" ? "failing" : "passing" end @@ -66,8 +66,16 @@ def update_state(result) end end + condition = state != state_was + + if respond_to?(:last_results_hash) + results_hash = Digest::MD5.hexdigest(result.rows.to_json) + condition = results_hash != last_result if check_type == 'new_bad_data' + self.last_results_hash = results_hash + end + # do not notify on creation, except when not passing - if (state_was != "new" || state != "passing") && state != state_was + if (state_was != "new" || state != "passing") && condition Blazer::CheckMailer.state_change(self, state, state_was, result.rows.size, message, result.columns, result.rows.first(10).as_json, result.column_types, check_type).deliver_now if emails.present? Blazer::SlackNotifier.state_change(self, state, state_was, result.rows.size, message, check_type) end diff --git a/app/views/blazer/check_mailer/state_change.html.erb b/app/views/blazer/check_mailer/state_change.html.erb index dce9ac61d..34323125a 100644 --- a/app/views/blazer/check_mailer/state_change.html.erb +++ b/app/views/blazer/check_mailer/state_change.html.erb @@ -6,7 +6,7 @@

<%= link_to "View", query_url(@check.query_id) %>

<% if @error %>

<%= @error %>

- <% elsif @rows_count > 0 && @check_type == "bad_data" %> + <% elsif @rows_count > 0 && %w[bad_data new_bad_data].include?(@check_type) %>

<% if @rows_count <= 10 %> <%= pluralize(@rows_count, "row") %> diff --git a/app/views/blazer/checks/_form.html.erb b/app/views/blazer/checks/_form.html.erb index 3e6020604..c555f5962 100644 --- a/app/views/blazer/checks/_form.html.erb +++ b/app/views/blazer/checks/_form.html.erb @@ -25,6 +25,7 @@ <%= f.label :check_type, "Alert if" %>

<% check_options = [["Any results (bad data)", "bad_data"], ["No results (missing data)", "missing_data"]] %> + <% check_options << ["Any new results (more bad data)", "new_bad_data"] if @check.respond_to?(:last_results_hash) %> <% check_options << ["Anomaly (most recent data point)", "anomaly"] if Blazer.anomaly_checks %> <%= f.select :check_type, check_options %>
diff --git a/lib/blazer/slack_notifier.rb b/lib/blazer/slack_notifier.rb index 8a03d5f06..c724a850f 100644 --- a/lib/blazer/slack_notifier.rb +++ b/lib/blazer/slack_notifier.rb @@ -7,7 +7,7 @@ def self.state_change(check, state, state_was, rows_count, error, check_type) text = if error error - elsif rows_count > 0 && check_type == "bad_data" + elsif rows_count > 0 && %w[bad_data new_bad_data].include?(check_type) pluralize(rows_count, "row") end diff --git a/lib/generators/blazer/templates/install.rb.tt b/lib/generators/blazer/templates/install.rb.tt index bf1999303..f968e46d1 100644 --- a/lib/generators/blazer/templates/install.rb.tt +++ b/lib/generators/blazer/templates/install.rb.tt @@ -39,6 +39,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version t.text :emails t.text :slack_channels t.string :check_type + t.string :last_results_hash t.text :message t.datetime :last_run_at t.timestamps null: false diff --git a/test/checks_test.rb b/test/checks_test.rb index c87934ead..71e4c350b 100644 --- a/test/checks_test.rb +++ b/test/checks_test.rb @@ -66,6 +66,25 @@ def test_emails end end + def test_emails_for_new_bad_data + query = create_query + check = create_check(query: query, check_type: "new_bad_data", emails: "hi@example.org,hi2@example.org") + + assert_emails 1 do + Blazer.run_checks(schedule: "5 minutes") + end + + assert_emails 0 do + Blazer.run_checks(schedule: "5 minutes") + end + + query.update!(statement: "SELECT 1 LIMIT 0") + + assert_emails 1 do + Blazer.run_checks(schedule: "5 minutes") + end + end + def test_slack query = create_query check = create_check(query: query, check_type: "bad_data", slack_channels: "#general,#random") @@ -83,6 +102,25 @@ def test_slack end end + def test_slack_for_new_bad_data + query = create_query + check = create_check(query: query, check_type: "new_bad_data", slack_channels: "#general,#random") + + assert_slack_messages 2 do + Blazer.run_checks(schedule: "5 minutes") + end + + assert_slack_messages 0 do + Blazer.run_checks(schedule: "5 minutes") + end + + query.update!(statement: "SELECT 1 LIMIT 0") + + assert_slack_messages 2 do + Blazer.run_checks(schedule: "5 minutes") + end + end + def assert_slack_messages(expected) count = 0 Blazer::SlackNotifier.stub :post_api, ->(*) { count += 1 } do diff --git a/test/internal/db/schema.rb b/test/internal/db/schema.rb index b8355bfe8..30ffcf2c2 100644 --- a/test/internal/db/schema.rb +++ b/test/internal/db/schema.rb @@ -38,6 +38,7 @@ t.text :emails t.text :slack_channels t.string :check_type + t.string :last_results_hash t.text :message t.datetime :last_run_at t.timestamps null: false