Module: NOCH

Defined in:
lib/noch.rb,
lib/NOCH/version.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.alert_nameObject

Returns the name of the alert



39
40
41
# File 'lib/noch.rb', line 39

def alert_name
  @@alert_name
end

.changed(to, data) ⇒ String, Hash

Returns the current status if the passed status is differente. If there is no current status save passed status with default data

Parameters:

  • to: (String)

    the status to be evaluated

Returns:

  • (String)

    status: if passed value is different

  • (Hash)

    Data: data to be saved



47
48
49
50
51
52
53
54
55
# File 'lib/noch.rb', line 47

def changed to, data
  if (current = self.get_status)
    current_status = ::JSON.parse(current)['status']
    return current_status if current_status != to
    to
  else
    NOCH.create_object(to, data)
  end
end

.contentObject



194
195
196
# File 'lib/noch.rb', line 194

def content
  @@content ||= IO.read(@@alert_file + ".rb").split("\n")
end

.create_object(to, data) ⇒ Object

Saves into Redis the alert with ‘to` as initial status

Parameters:

  • to: (String)

    the value of the status to be saved

  • data: (Hash)

    the data to be saved

Raises:

  • (StandardError)


86
87
88
89
# File 'lib/noch.rb', line 86

def create_object(to, data)
  return to if @@redis.set(@@alert_name, self.default(to, data).to_json) == "OK"
  raise StandardError.new("Status `#{to}` could not be saved")
end

.default(to, data = nil) ⇒ Hash

Sets default status. Used the first time execution with passed status

Parameters:

  • to: (String)

    the status to be saved

Returns:

  • (Hash)


14
15
16
17
18
19
# File 'lib/noch.rb', line 14

def default to, data = nil
  {
    "status" => to,
    "data" => data
  }
end

.evaluate_for(what, opts = nil) ⇒ Boolean

Sends notification if status change. If not returns nil def evaluate_for what, message = nil, data = nil

Parameters:

  • what: (String)

    current status

  • opts: (optional)

    The arguments. Could be String for only message text or a Hash to pass :message and :data

Returns:

  • (Boolean)

    true if notification is sent, false if nothing changed



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/noch.rb', line 68

def evaluate_for what, opts = nil
  if opts.is_a? Hash
    message = opts.delete(:message)
    data = opts.delete(:data)
  else
    message = opts
  end
  raise "Unknown status #{what}. Allowed: ['ok','warning','critical','skip']" unless ['ok','warning','critical','skip'].include? what
  from = self.changed(what, data)
  !!(if (from != what)
      self.set what, message, data
      self.notify(from, what, message, data) unless what == 'skip'
  end)
end

.get_statusHash

Returns the current status of the alert

Returns:

  • (Hash)

    “last_change”=>“2019-07-17T22:51:03.081-03:00”, “message”=>nil, “data”=>nil



59
60
61
# File 'lib/noch.rb', line 59

def get_status
  @@redis.get(@@alert_name)
end

.included(base) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/noch.rb', line 21

def included(base)
  @@alert_file = caller.select{|l| l.include? "`include'"}.first.split(".").first
  @@alert_name = @@alert_file.split('/').last.split('_').map{|w| w.capitalize}.join(" ")
  @@redis_host = ENV['REDIS_HOST'] || 'localhost'
  @@redis_port = ENV['REDIS_PORT'] || '6379'
  @@redis ||= ::Redis.new(host: @@redis_host, port: @@redis_port)
  @@slack_client = if ENV['SLACK_API_TOKEN']
    ::Slack.configure do |config|
      config.token = ENV['SLACK_API_TOKEN']
    end
    ::Slack::Web::Client.new
  end
  @@telegram_client = if ENV['TELEGRAM_TOKEN'] and ENV['TELEGRAM_USER']
    ::Telegram::Bot::Client.new(ENV['TELEGRAM_TOKEN'], ENV['TELEGRAM_USER'])
  end
end

.matched_line(what) ⇒ String

To get config token and/or values, e.g for slack, returns values from line containing arg will return 1234567890987654321 when param what is SLACK

Parameters:

  • what (String)

    configuration name. E.g.

    # SLACK 1234567890987654321

Returns:

  • (String)

    value for line staring with ‘# <something> `



187
188
189
190
191
192
# File 'lib/noch.rb', line 187

def matched_line what
  line = self.content.select do |line|
    line.start_with? "# #{what} "
  end.first
  line.split("# #{what.upcase} ").last if line
end

.notify(from, to, message, data = nil) ⇒ Boolean

Prints out notification information and sends it

Parameters:

  • from: (String)

    the previous status

  • to: (Strig)

    the current status

  • data (Hash) (defaults to: nil)

    (optional): the data to be saved

Returns:

  • (Boolean)

    true if notification sent. false if not



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/noch.rb', line 110

def notify from, to, message, data = nil
  string = "Alert: #{@@alert_name}

[ #{from} ] => [ #{to} ]
  
#{message}
  
  "
  string += "
  
  Data: 
  #{data}
  " if data
  print string
  self.send_slack(string)
  self.send_telegram(string)
end

.send_slack(message = nil) ⇒ Boolean

Sends message notification through Slack to the given slack channel

Parameters:

  • message: (String)

    the message string to be sent

Returns:

  • (Boolean)

    true if notification sent. false if not



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/noch.rb', line 131

def send_slack message = nil
  channel = self.slack
  if channel and !!@@slack_client
    @@slack_client.auth_test
    if message
      begin
        puts "Enviando: #{message}
        to: #{channel}"
        @@slack_client.chat_postMessage(channel: channel, text: message, as_user: true)
        true
      rescue
        puts "Error sending message to slack channel #{channel}"
        false
      end
    end
  end
end

.send_telegram(message = nil) ⇒ Boolean

Sends message notification through Slack to the given slack channel

Parameters:

  • message: (String)

    the message string to be sent

Returns:

  • (Boolean)

    true if notification sent. false if not



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/noch.rb', line 157

def send_telegram message = nil
  chat_id = self.telegram
  if chat_id and !!@@telegram_client
    if message
      begin
        puts "Enviando: #{message}
        to: #{chat_id}"
        @@telegram_client.send_message(chat_id: chat_id, text: message)
        true
      rescue
        puts "Error sending message to telegram group #{group_id}"
        false
      end
    end
  end
end

.set(to, message = nil, data = nil) ⇒ Object

Saves status, message and data into Redis

Parameters:

  • to: (String)

    status to save. It could be [‘ok’,‘warning’,‘skip’,‘critical’]

  • message (String) (defaults to: nil)

    (optional): The message to be sent on notification

  • data(optional): (Hash)

    data to be saved for future evaluation if needed



95
96
97
98
99
100
101
102
103
# File 'lib/noch.rb', line 95

def set to, message = nil, data = nil
  data = {
    'status' => to,
    'last_change' => Time.now,
    'message' => message,
    'data' => data
  }
  @@redis.set @@alert_name, data.to_json
end

.slackObject

Returns value for slack token



150
151
152
# File 'lib/noch.rb', line 150

def slack
  self.matched_line("SLACK")&.strip
end

.telegramObject

Returns value for telegram group id



175
176
177
# File 'lib/noch.rb', line 175

def telegram
  self.matched_line("TELEGRAM")&.strip
end

Instance Method Details

#alert_nameObject



252
253
254
# File 'lib/noch.rb', line 252

def alert_name
  @@alert_name
end

#critical!(opts = nil) ⇒ Object

use to set status to critical :message :data

Parameters:

  • opts (Hash) (defaults to: nil)


227
228
229
# File 'lib/noch.rb', line 227

def critical! opts = nil
  NOCH.evaluate_for "critical", opts
end

#get_currentHash

Returns the current status. Useful when you save aditional data into status

Returns:

  • (Hash)

    “last_change”=>“2019-07-17T22:51:03.081-03:00”, “message”=>nil, “data”=>nil



242
243
244
# File 'lib/noch.rb', line 242

def get_current
  JSON.parse(NOCH.get_status)
end

#inspectObject



256
257
258
259
260
261
# File 'lib/noch.rb', line 256

def inspect
  {
    "version" => VERSION,
    "alert_name" => @@alert_name
  }
end

#last_dataString

Returns the last data saved

Returns:

  • (String)

    last data saved



248
249
250
# File 'lib/noch.rb', line 248

def last_data
  get_current['data']
end

#ok!(opts = nil) ⇒ Object

use to set status to ok :message :data

Parameters:

  • opts (Hash) (defaults to: nil)


207
208
209
# File 'lib/noch.rb', line 207

def ok! opts = nil
  NOCH.evaluate_for "ok", opts
end

#skip!(opts = nil) ⇒ Object

:message :data

Parameters:

  • opts (Hash) (defaults to: nil)


236
237
238
# File 'lib/noch.rb', line 236

def skip! opts = nil
  NOCH.evaluate_for "skip", opts
end

#warning!(opts = nil) ⇒ Object

use to set status to warning :message :data

Parameters:

  • opts (Hash) (defaults to: nil)


217
218
219
# File 'lib/noch.rb', line 217

def warning! opts = nil
  NOCH.evaluate_for "warning", opts
end