Class: Blazer::SlackNotifier

Inherits:
Object
  • Object
show all
Defined in:
lib/blazer/slack_notifier.rb

Class Method Summary collapse

Class Method Details

.channel_failing_checks(channel, checks) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/blazer/slack_notifier.rb', line 60

def self.channel_failing_checks(channel, checks)
  text =
    checks.map do |check|
      "<#{query_url(check.query_id)}|#{escape(check.query.name)}> #{escape(check.state)}"
    end

  payload = {
    channel: channel,
    attachments: [
      {
        title: escape("#{pluralize(checks.size, "Check")} Failing"),
        text: text.join("\n"),
        color: "warning"
      }
    ]
  }

  post(payload)
end

.escape(str) ⇒ Object

https://api.slack.com/docs/message-formatting#how_to_escape_characters

  • Replace the ampersand, &, with &
  • Replace the less-than sign, < with <
  • Replace the greater-than sign, > with > That's it. Don't HTML entity-encode the entire message.


85
86
87
# File 'lib/blazer/slack_notifier.rb', line 85

def self.escape(str)
  str.gsub("&", "&amp;").gsub("<", "&lt;").gsub(">", "&gt;") if str
end

.failing_checks(checks) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/blazer/slack_notifier.rb', line 3

def self.failing_checks(checks)
  slack_channels = {}
  checks.each do |check|
    split_slack_channels(check).each do |channel|
      (slack_channels[channel] ||= []) << check
    end
  end
  slack_channels.each do |channel, checks|
    Safely.safely do
      channel_failing_checks(channel, checks)
    end
  end
end

.fieldsObject



48
49
50
# File 'lib/blazer/slack_notifier.rb', line 48

def self.fields
  Blazer.slack? ? [:slack_channels] : []
end

.notify_list(check) ⇒ Object

TODO improve name



44
45
46
# File 'lib/blazer/slack_notifier.rb', line 44

def self.notify_list(check)
  split_slack_channels(check)
end

.pluralize(*args) ⇒ Object



89
90
91
# File 'lib/blazer/slack_notifier.rb', line 89

def self.pluralize(*args)
  ActionController::Base.helpers.pluralize(*args)
end

.post(payload) ⇒ Object

TODO use return value



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/blazer/slack_notifier.rb', line 101

def self.post(payload)
  require "net/http"

  if Blazer.slack_webhook_url.present?
    response = post_api(Blazer.slack_webhook_url, payload, {})
    response.is_a?(Net::HTTPSuccess) && response.body == "ok"
  else
    headers = {
      "Authorization" => "Bearer #{Blazer.slack_oauth_token}",
      "Content-type" => "application/json"
    }
    response = post_api("https://slack.com/api/chat.postMessage", payload, headers)
    response.is_a?(Net::HTTPSuccess) && (JSON.parse(response.body)["ok"] rescue false)
  end
end

.post_api(url, payload, headers) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/blazer/slack_notifier.rb', line 117

def self.post_api(url, payload, headers)
  uri = URI.parse(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.open_timeout = 3
  http.read_timeout = 5
  http.post(uri.request_uri, payload.to_json, headers)
end

.query_url(id) ⇒ Object

checks shouldn't have variables, but in any case, avoid passing variable params to url helpers (known unsafe parameters are removed, but still not ideal)



96
97
98
# File 'lib/blazer/slack_notifier.rb', line 96

def self.query_url(id)
  Blazer::Engine.routes.url_helpers.query_url(id, ActionMailer::Base.default_url_options)
end

.split_slack_channels(check) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/blazer/slack_notifier.rb', line 52

def self.split_slack_channels(check)
  if Blazer.slack?
    check.slack_channels.to_s.downcase.split(",").map(&:strip)
  else
    []
  end
end

.state_change(check:, state:, state_was:, result:, message:, check_type:) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/blazer/slack_notifier.rb', line 17

def self.state_change(check:, state:, state_was:, result:, message:, check_type:)
  rows_count = result.rows.size
  split_slack_channels(check).each do |channel|
    text =
      if message
        message
      elsif rows_count > 0 && check_type == "bad_data"
        pluralize(rows_count, "row")
      end

    payload = {
      channel: channel,
      attachments: [
        {
          title: escape("Check #{state.titleize}: #{check.query.name}"),
          title_link: query_url(check.query_id),
          text: escape(text),
          color: state == "passing" ? "good" : "danger"
        }
      ]
    }

    post(payload)
  end
end