Class: NagiosHerald::Formatter

Inherits:
Object
  • Object
show all
Includes:
Logging, Util
Defined in:
lib/nagios-herald/formatters/base.rb,
lib/nagios-herald/formatters/example.rb,
lib/nagios-herald/formatters/check_cpu.rb,
lib/nagios-herald/formatters/check_disk.rb,
lib/nagios-herald/formatters/check_memory.rb,
lib/nagios-herald/formatters/check_logstash.rb,
lib/nagios-herald/formatters/check_graphite_graph.rb

Defined Under Namespace

Classes: CheckCpu, CheckDisk, CheckGraphiteGraph, CheckLogstash, CheckMemory, Example

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

#get_nagios_var, get_script_path, load_helper, underscore_to_camel_case, #unescape_text

Methods included from Logging

#configure_logger_for, #logger, #logger_for

Constructor Details

#initialize(options) ⇒ Formatter

Returns a new instance of Formatter.



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/nagios-herald/formatters/base.rb', line 28

def initialize(options)
  @content = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) } # autovivify
  @content[:attachments] = []
  @content[:html]
  @content[:subject] = ""
  @content[:text]
  @content[:short_text]
  @nagios_url = options[:nagios_url]
  @sandbox  = get_sandbox_path
  @state_type = get_nagios_var("NAGIOS_SERVICESTATE") != "" ? "SERVICE" : "HOST"

end

Instance Attribute Details

#contentObject

all the content required to generate a message



24
25
26
# File 'lib/nagios-herald/formatters/base.rb', line 24

def content
  @content
end

#sandboxObject

Returns the value of attribute sandbox.



25
26
27
# File 'lib/nagios-herald/formatters/base.rb', line 25

def sandbox
  @sandbox
end

#state_typeObject

Returns the value of attribute state_type.



26
27
28
# File 'lib/nagios-herald/formatters/base.rb', line 26

def state_type
  @state_type
end

Class Method Details

.formattersObject



41
42
43
# File 'lib/nagios-herald/formatters/base.rb', line 41

def self.formatters
  @@formatters ||= {}
end

.inherited(subclass) ⇒ Object

Public: When subclassed formatters are instantiated, add them to the @@formatters hash. The key is the downcased and snake_cased name of the class file (i.e. check_disk); the value is the actual class (i.e. CheckDisk) so that we can easily instantiate formatters when we know the formatter name. Learned this pattern thanks to the folks at Chef and @jonlives. See github.com/opscode/chef/blob/11-stable/lib/chef/knife.rb#L79#L83

Returns the formatters hash.



53
54
55
56
57
58
59
# File 'lib/nagios-herald/formatters/base.rb', line 53

def self.inherited(subclass)
  subclass_base_name = subclass.name.split('::').last
  subclass_base_name.gsub!(/[A-Z]/) { |s| "_" + s } # replace uppercase with underscore and lowercase
  subclass_base_name.downcase!
  subclass_base_name.sub!(/^_/, "")   # strip the leading underscore
  formatters[subclass_base_name] = subclass
end

Instance Method Details

#ack_infoObject

Public: Formats the information about who ack’d the alert and when Generates text and HTML output.



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/nagios-herald/formatters/base.rb', line 348

def ack_info
  section = __method__
  text = ""
  short_text = ""
  html = ""
  date = get_nagios_var("NAGIOS_LONGDATETIME")
  author = get_nagios_var("NAGIOS_#{@state_type}ACKAUTHOR")
  comment = get_nagios_var("NAGIOS_#{@state_type}ACKCOMMENT")
  hostname = get_nagios_var("NAGIOS_HOSTNAME")

  text       += "At #{date} #{author}"
  short_text += "At #{date} #{author}"
  html       += "At #{date} #{author}"

  if @state_type == "SERVICE"
    desc = get_nagios_var("NAGIOS_SERVICEDESC")
    text       += " acknowledged #{hostname}/#{desc}.\n\n"
    short_text += " acked #{hostname}/#{desc}.\n\n"
    html       += " acknowledged #{hostname}/#{desc}.<br><br>"
  else
    text       += " acknowledged #{hostname}.\n\n"
    short_text += " acked #{hostname}.\n\n"
    html       += " acknowledged #{hostname}.<br><br>"

  end
  text       += "Comment: #{comment}" if comment
  short_text += "#{comment}" if comment
  html       += "Comment: #{comment}" if comment
  add_text(section, text)
  add_short_text(section, short_text)
  add_html(section, html)
end

#action_urlObject

Public: Formats the action URL for this alert. Generates text and HTML output.



307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/nagios-herald/formatters/base.rb', line 307

def action_url
  section = __method__
  text = ""
  html = ""
  action_url = get_nagios_var("NAGIOS_#{@state_type}ACTIONURL")
  if !action_url.nil? and !action_url.empty?
    text += "Action URL: #{action_url}\n\n"
    html += "<b>Action URL</b>: #{action_url}<br><br>"
  end
  add_text(section, text)
  add_html(section, html)
end

#add_attachment(path) ⇒ Object

Public: Add an attachment’s path to an array.

path - The fully qualified path for a file attachment

Example:

add_attachment("/tmp/file-to-attach.txt")

Returns the array of attachment paths.



155
156
157
158
# File 'lib/nagios-herald/formatters/base.rb', line 155

def add_attachment(path)
  #@attachments << path
  @content[:attachments] << path
end

#add_html(section, html) ⇒ Object

Public: Concatenates HTML content.

section - The content section name whose HTML we’ll concatenate text - The HTML we want to concatenate

Example:

add_html("state_detail", "Service is somewhere in Kansas")

Returns the concatenated HTML for the given section.



136
137
138
139
140
141
142
143
144
# File 'lib/nagios-herald/formatters/base.rb', line 136

def add_html(section, html)
  # Ensure our key is a symbol, regardless if we're passed a string or symbol
  section = section.to_sym
  if @content[:html][section].nil? or @content[:html][section].empty?
    @content[:html][section] = html
  else
    @content[:html][section] += html
  end
end

#add_short_text(section, text) ⇒ Object

Public: Concatenates short text content. This is really for usage in limited space messages like SMS or chat based mediums.

section - The content section name whose text we’ll concatenate text - The text we want to concatenate

Example:

add_short_text("state_detail", "Service is somewhere in Kansas")

Returns the concatenated short text for the given section.



116
117
118
119
120
121
122
123
124
# File 'lib/nagios-herald/formatters/base.rb', line 116

def add_short_text(section, text)
  # Ensure our key is a symbol, regardless if we're passed a string or symbol
  section = section.to_sym
  if @content[:short_text][section].nil? or @content[:short_text][section].empty?
    @content[:short_text][section] = text
  else
    @content[:short_text][section] += text
  end
end

#add_text(section, text) ⇒ Object

Public: Concatenates text content.

section - The content section name whose text we’ll concatenate text - The text we want to concatenate

Example:

add_text("state_detail", "Service is somewhere in Kansas")

Returns the concatenated HTML for the given section.



95
96
97
98
99
100
101
102
103
# File 'lib/nagios-herald/formatters/base.rb', line 95

def add_text(section, text)
  # Ensure our key is a symbol, regardless if we're passed a string or symbol
  section = section.to_sym
  if @content[:text][section].nil? or @content[:text][section].empty?
    @content[:text][section] = text
  else
    @content[:text][section] += text
  end
end

#additional_detailsObject

Public: Formats information provided plugin’s long output. Generates text and HTML output.



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/nagios-herald/formatters/base.rb', line 268

def additional_details
  section = __method__
  text = ""
  short_text = ""
  html = ""
  long_output = get_nagios_var("NAGIOS_LONG#{@state_type}OUTPUT")
  if !long_output.nil? and !long_output.empty?
    text += "Additional Details: #{unescape_text(long_output)}\n"
    short_text += "#{unescape_text(long_output)}\n"
    html += "<b>Additional Details</b>: <pre>#{unescape_text(long_output)}</pre><br><br>"
    add_text(section, text)
    add_short_text(section, short_text)
    add_html(section, html)
  end
end

#additional_infoObject

Public: Formats information provided plugin’s output. Generates text and HTML output.



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/nagios-herald/formatters/base.rb', line 250

def additional_info
  section = __method__
  text = ""
  short_text = ""
  html = ""
  output = get_nagios_var("NAGIOS_#{@state_type}OUTPUT")
  if !output.nil? and !output.empty?
    text += "Additional Info: #{unescape_text(output)}\n\n"
    short_text += "#{unescape_text(output)}\n\n"
    html += "<b>Additional Info</b>: #{output}<br><br>"
    add_text(section, text)
    add_short_text(section, short_text)
    add_html(section, html)
  end
end

#alert_ack_urlObject

Public: Formats the URI one can click to acknowledge an alert (i.e. in an email) Generates text and HTML output.



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/nagios-herald/formatters/base.rb', line 412

def alert_ack_url
  section = __method__
  text = ""
  html = ""
  hostname  = get_nagios_var("NAGIOS_HOSTNAME")
  service_desc = get_nagios_var("NAGIOS_SERVICEDESC")

  if service_desc != ""
    url = "#{@nagios_url}/nagios/cgi-bin/cmd.cgi?cmd_typ=34&host=#{hostname}&service=#{service_desc}"
  else
    url = "#{@nagios_url}/nagios/cgi-bin/cmd.cgi?cmd_typ=33&host=#{hostname}"
  end
  url = URI.escape(url)
  text += "Acknowledge this alert: #{url}\n"
  text += "Alternatively, reply to this message with the word 'ack' in the body to acknowledge the alert.\n"
  html += "Acknowledge this alert: #{url}<br>"
  html += "Alternatively, <b>reply</b> to this message with the word '<b><font color='green'>ack</font></b>' in the body to acknowledge the alert.<br>"
  add_text(section, text)
  add_html(section, html)
end

#clean_sandboxObject

Public: Does some housecleaning on the sandbox, if it exists.



590
591
592
# File 'lib/nagios-herald/formatters/base.rb', line 590

def clean_sandbox
  FileUtils.remove_entry @sandbox if File.directory?(@sandbox)
end

#delete_html(section) ⇒ Object



72
73
74
# File 'lib/nagios-herald/formatters/base.rb', line 72

def delete_html(section)
  delete_section_for_type(:html, section)
end

#delete_section_for_type(type, section) ⇒ Object

Public: remove a section from the content hash

section - section to remove

Returns the content that got removed or nil if the type or section doesn’t exist



67
68
69
70
# File 'lib/nagios-herald/formatters/base.rb', line 67

def delete_section_for_type(type, section)
  return nil if @content[type].nil?
  @content[type].delete(section)
end

#delete_short_text(section) ⇒ Object



80
81
82
# File 'lib/nagios-herald/formatters/base.rb', line 80

def delete_short_text(section)
  delete_section_for_type(:short_text, section)
end

#delete_text(section) ⇒ Object



76
77
78
# File 'lib/nagios-herald/formatters/base.rb', line 76

def delete_text(section)
  delete_section_for_type(:text, section)
end

#end_section(section) ⇒ Object

Public: Ends a format section’s HTML <div> block.

section - The name of the section whose HTML we’ll start.

Example

start_section("additional_details")

Generates an ending HTML <div> tag.



467
468
469
# File 'lib/nagios-herald/formatters/base.rb', line 467

def end_section(section)
  add_html(section, "</div>")
end

#generate_ack_contentObject

Public: Generate content for ACKNOWLEGEMENT alerts



515
516
517
518
# File 'lib/nagios-herald/formatters/base.rb', line 515

def generate_ack_content
  generate_section("host_info")
  generate_section("ack_info")
end

#generate_content(nagios_notification_type) ⇒ Object

Public: Dispatch method to help generate content based on notification type.

nagios_notification_type - One of any valid Nagios notification types.

Example

generate_content("PROBLEM")


529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/nagios-herald/formatters/base.rb', line 529

def generate_content(nagios_notification_type)
  case nagios_notification_type
    when "PROBLEM", "FLAPPINGSTART"
      generate_problem_content
    when "RECOVERY", "FLAPPINGSTOP"
      generate_recovery_content
    when "ACKNOWLEDGEMENT"
      generate_ack_content
    else
      logger.fatal "Invalid Nagios notification type! Expecting something like PROBLEM or RECOVERY. We got #{nagios_notification_type}."
      exit 1
  end
end

#generate_message_contentObject

Public: Generates content body.

Call various formatting methods that each generate content for their given sections.



574
575
576
577
578
# File 'lib/nagios-herald/formatters/base.rb', line 574

def generate_message_content
    generate_subject
    nagios_notification_type = get_nagios_var('NAGIOS_NOTIFICATIONTYPE')
    generate_content(nagios_notification_type)
end

#generate_problem_contentObject

Public: Generate content for PROBLEM alerts.



490
491
492
493
494
495
496
497
498
499
500
# File 'lib/nagios-herald/formatters/base.rb', line 490

def generate_problem_content
  generate_section("host_info")
  generate_section("state_info")
  generate_section("additional_info")
  generate_section("action_url")
  generate_section("notes")
  generate_section("additional_details")
  generate_section("recipients_email_link")
  generate_section("notification_info")
  generate_section("alert_ack_url")
end

#generate_recovery_contentObject

Public: Generate content for RECOVERY alerts.



503
504
505
506
507
508
509
510
511
512
# File 'lib/nagios-herald/formatters/base.rb', line 503

def generate_recovery_content
  generate_section("host_info")
  generate_section("state_info", "color:green")
  generate_section("additional_info")
  generate_section("action_url")
  generate_section("notes")
  generate_section("additional_details")
  generate_section("recipients_email_link")
  generate_section("notification_info")
end

#generate_section(section, *section_style_args) ⇒ Object

Public: Wrapper for starting a format section, calling the format method, and ending the section.

section - The name of the section whose HTML we’ll start. *section_style_args - A list of style attributes to be used in the <div> block for the section.

Example:

generate_section("additional_info", "color:green", "font-weight:bold") - Color all text green and bold it
generate_section("additional_info") - Color all text green

Calls the relevant section method to generate content.



483
484
485
486
487
# File 'lib/nagios-herald/formatters/base.rb', line 483

def generate_section(section, *section_style_args)
  start_section(section, *section_style_args)
  self.send(section)
  end_section(section)
end

#generate_subjectObject

Public: Generates a subject.

Returns a subject.



546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/nagios-herald/formatters/base.rb', line 546

def generate_subject
  hostname          = get_nagios_var("NAGIOS_HOSTNAME")
  service_desc      = get_nagios_var("NAGIOS_SERVICEDESC")
  notification_type = get_nagios_var("NAGIOS_NOTIFICATIONTYPE")
  state             = get_nagios_var("NAGIOS_#{@state_type}STATE")

  subject="#{hostname}"
  subject += "/#{service_desc}" if service_desc != ""

  if @state_type == "SERVICE"
    long_subject="#{notification_type} Service #{subject} is #{state}"
  else
    long_subject="#{notification_type} Host #{subject} is #{state}"
  end

  if notification_type == "ACKNOWLEDGEMENT"
    short_subject="ACK: #{subject} is #{state}"
  else
    short_subject="#{subject} is #{state}"
  end

  @content[:subject] = long_subject
  @content[:short_subject] = short_subject
end

#get_sandbox_pathObject

Public: Creates a temporary directory in which to create files used in attachments.

Returns the path to a temporary directory.



584
585
586
587
# File 'lib/nagios-herald/formatters/base.rb', line 584

def get_sandbox_path
  @sandbox = Dir.mktmpdir if @sandbox.nil?
  return @sandbox
end

#host_infoObject

Public: Formats the information about the host that’s being alerted on. Generates text and HTML output.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/nagios-herald/formatters/base.rb', line 181

def host_info
  section = __method__
  text = ""
  short_text = ""
  html = ""
  hostname          = get_nagios_var("NAGIOS_HOSTNAME")
  service_desc      = get_nagios_var("NAGIOS_SERVICEDESC")
  text += "Host: #{hostname} "
  short_text += "#{hostname}"
  html += "<br><b>Host</b>: #{hostname} "
  if !service_desc.nil? and !service_desc.empty?
    text += "Service: #{service_desc}\n"
    short_text += "/#{service_desc}\n"
    html += "<b>Service</b>: #{service_desc}<br/>"
  else
    # we need a trailing newline if no service description
    line_break(section)
  end
  add_text(section, text)
  add_short_text(section, short_text)
  add_html(section, html)
  line_break(section)
end

#line_break(section) ⇒ Object

Public: Appends a newline in text and HTML format.

section - The content section name that needs the line break

Example

line_break(additional_info)

Appends text and HTML output to the appropriate sections in @content



173
174
175
176
177
# File 'lib/nagios-herald/formatters/base.rb', line 173

def line_break(section)
  add_text(section, "\n")
  add_short_text(section, "\n")
  add_html(section, "<br>")
end

#notesObject

Public: Formats the notes information for this alert. Generates text and HTML output.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/nagios-herald/formatters/base.rb', line 286

def notes
  section = __method__
  text = ""
  html = ""
  notes = get_nagios_var("NAGIOS_#{@state_type}NOTES")
  if !notes.nil? and !notes.empty?
    text += "Notes: #{unescape_text(notes)}\n\n"
    html += "<b>Notes</b>: #{notes}<br><br>"
  end

  notes_url = get_nagios_var("NAGIOS_#{@state_type}NOTESURL")
  if !notes_url.nil? and !notes_url.empty?
    text += "Notes URL: #{notes_url}\n\n"
    html += "<b>Notes URL</b>: #{notes_url}<br><br>"
  end
  add_text(section, text)
  add_html(section, html)
end

#notification_infoObject

Public: Formats information about the notification. Provides information such as the date and notification number. Generates text and HTML output.



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/nagios-herald/formatters/base.rb', line 236

def notification_info
  section = __method__
  text = ""
  html = ""
  date   = get_nagios_var("NAGIOS_LONGDATETIME")
  number = get_nagios_var("NAGIOS_NOTIFICATIONNUMBER")
  text += "Notification sent at: #{date} (notification number #{number})\n\n"
  html += "Notification sent at: #{date} (notification number #{number})<br><br>"
  add_text(section, text)
  add_html(section, html)
end

Public: Formats the email recipients and URIs Generates text and HTML output.



334
335
336
337
338
339
340
341
342
343
344
# File 'lib/nagios-herald/formatters/base.rb', line 334

def recipients_email_link
  section = __method__
  text = ""
  html = ""
  recipients = get_nagios_var("NAGIOS_NOTIFICATIONRECIPIENTS")
  return if recipients.nil?
  text += "Sent to #{recipients}\n\n"
  html += "Sent to #{recipients}<br><br>"
  add_text(section, text)
  add_html(section, html)
end

#short_ack_infoObject

Public: Formats brief ack information. Useful for pager messages. Generates text and HTML output.



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/nagios-herald/formatters/base.rb', line 384

def short_ack_info
  section = __method__
  text = ""
  html = ""
  author    = get_nagios_var("NAGIOS_#{@state_type}ACKAUTHOR")
  comment   = get_nagios_var("NAGIOS_#{@state_type}COMMENT")
  hostname  = get_nagios_var("NAGIOS_HOSTNAME")

  text += "#{author}  ack'd "
  html += "#{author}  ack'd "

  if @state_type == "SERVICE"
    desc = get_nagios_var("NAGIOS_SERVICEDESC")
    text += "#{desc} on #{hostname}.\n"
    html += "#{desc} on #{hostname}.<br>"
  else
    text += "#{hostname}.\n"
    html += "#{hostname}.<br>"

  end
  text += "Comment: #{comment}" if comment
  html += "Comment: #{comment}" if comment
  add_text(section, text)
  add_html(section, html)
end

#short_state_detailObject

FIXME: Looks like a dupe of #additional_info (used in pager alerts, it seems)



321
322
323
324
325
326
327
328
329
330
# File 'lib/nagios-herald/formatters/base.rb', line 321

def short_state_detail
  section = __method__
  text = ""
  html = ""
  output   = get_nagios_var("NAGIOS_#{@state_type}OUTPUT")
  text += "#{output}\n"
  html += "#{output}<br>"
  add_text(section, text)
  add_html(section, html)
end

#start_section(section, *section_style_args) ⇒ Object

Public: Starts a format section’s HTML <div> block.

section - The name of the section whose HTML we’ll start. *section_style_args - CSS-type attributes used to style the content.

Example

start_section("additional_details", "color:green")

Generates HTML <div> block with the requested style.



447
448
449
450
451
452
453
454
455
456
# File 'lib/nagios-herald/formatters/base.rb', line 447

def start_section(section, *section_style_args)
  html = ""
  if !section_style_args.nil?
    style = section_style_args.join(';')
    html += "<div style='#{style}'>"
  else
    html += "<div>"
  end
  add_html(section, html)
end

#state_infoObject

Public: Formats information about the state of the thing being alerted on where ‘thing’ is either HOST or SERVICE. Generates text and HTML output.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/nagios-herald/formatters/base.rb', line 208

def state_info
  section = __method__
  text = ""
  short_text = ""
  html = ""
  state         = get_nagios_var("NAGIOS_#{@state_type}STATE")
  duration      = get_nagios_var("NAGIOS_#{@state_type}DURATION")
  last_state    = get_nagios_var("NAGIOS_LAST#{@state_type}STATE")
  attempts      = get_nagios_var("NAGIOS_#{@state_type}ATTEMPT")
  max_attempts  = get_nagios_var("NAGIOS_MAX#{@state_type}ATTEMPTS")

  text += "State is now: #{state} for #{duration} (was #{last_state}) after #{attempts} / #{max_attempts} checks\n"
  short_text += "#{state} for #{duration} (was #{last_state}) after #{attempts} / #{max_attempts} checks\n"

  if state.eql? 'OK' or state.eql? 'UP'
      html += "State is now: <b>#{state}</b> for <b>#{duration}</b> (was #{last_state}) after <b>#{attempts} / #{max_attempts}</b> checks<br/>"
  else
      html += "State is now: <b><font style='color:red'>#{state}</font></b> for <b>#{duration}</b> (was #{last_state}) after <b>#{attempts} / #{max_attempts}</b> checks<br/>"
  end
  add_text(section, text)
  add_short_text(section, short_text)
  add_html(section, html)
  line_break(section)
end