flapjack 0.7.28 → 0.7.29
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/features/notification_rules.feature +25 -25
- data/features/rollup.feature +38 -18
- data/features/steps/events_steps.rb +10 -5
- data/features/steps/notifications_steps.rb +8 -4
- data/lib/flapjack/data/alert.rb +207 -0
- data/lib/flapjack/data/contact.rb +14 -7
- data/lib/flapjack/data/entity_check.rb +4 -3
- data/lib/flapjack/data/notification.rb +28 -27
- data/lib/flapjack/gateways/api/contact_methods.rb +32 -12
- data/lib/flapjack/gateways/email.rb +49 -53
- data/lib/flapjack/gateways/email/alert.html.erb +15 -15
- data/lib/flapjack/gateways/email/alert.text.erb +15 -15
- data/lib/flapjack/gateways/email/alert_subject.text.erb +3 -13
- data/lib/flapjack/gateways/email/rollup.html.erb +6 -6
- data/lib/flapjack/gateways/email/rollup.text.erb +7 -7
- data/lib/flapjack/gateways/email/rollup_subject.text.erb +1 -19
- data/lib/flapjack/gateways/jabber.rb +57 -47
- data/lib/flapjack/gateways/jabber/alert.text.erb +12 -0
- data/lib/flapjack/gateways/jabber/rollup.text.erb +2 -0
- data/lib/flapjack/gateways/pagerduty.rb +60 -30
- data/lib/flapjack/gateways/pagerduty/alert.text.erb +10 -0
- data/lib/flapjack/gateways/sms_messagenet.rb +29 -36
- data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +4 -14
- data/lib/flapjack/gateways/sms_messagenet/rollup.text.erb +2 -34
- data/lib/flapjack/gateways/web.rb +23 -14
- data/lib/flapjack/gateways/web/views/check.html.erb +16 -11
- data/lib/flapjack/gateways/web/views/contact.html.erb +58 -16
- data/lib/flapjack/gateways/web/views/self_stats.html.erb +80 -71
- data/lib/flapjack/notifier.rb +8 -2
- data/lib/flapjack/pikelet.rb +17 -3
- data/lib/flapjack/processor.rb +0 -1
- data/lib/flapjack/redis_pool.rb +1 -1
- data/lib/flapjack/utility.rb +13 -0
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/data/contact_spec.rb +44 -29
- data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +24 -4
- data/spec/lib/flapjack/gateways/email_spec.rb +0 -5
- data/spec/lib/flapjack/gateways/jabber_spec.rb +5 -1
- data/spec/lib/flapjack/gateways/pagerduty_spec.rb +5 -2
- data/spec/lib/flapjack/gateways/{sms_messagenet.spec.rb → sms_messagenet_spec.rb} +16 -12
- data/spec/lib/flapjack/gateways/web_spec.rb +1 -1
- data/spec/spec_helper.rb +28 -6
- metadata +43 -89
@@ -25,7 +25,7 @@ module Flapjack
|
|
25
25
|
raise "Redis connection not set" unless redis = options[:redis]
|
26
26
|
|
27
27
|
redis.keys('contact:*').inject([]) {|ret, k|
|
28
|
-
k =~ /^contact:(
|
28
|
+
k =~ /^contact:(.*)$/
|
29
29
|
id = $1
|
30
30
|
contact = self.find_by_id(id, :redis => redis)
|
31
31
|
ret << contact if contact
|
@@ -129,6 +129,12 @@ module Flapjack
|
|
129
129
|
merge('service_key' => service_key)
|
130
130
|
end
|
131
131
|
|
132
|
+
def set_pagerduty_credentials(details)
|
133
|
+
@redis.hset("contact_media:#{self.id}", 'pagerduty', details['service_key'])
|
134
|
+
@redis.hmset("contact_pagerduty:#{self.id}",
|
135
|
+
*['subdomain', 'username', 'password'].collect {|f| [f, details[f]]})
|
136
|
+
end
|
137
|
+
|
132
138
|
# NB ideally contacts_for:* keys would scope the entity and check by an
|
133
139
|
# input source, for namespacing purposes
|
134
140
|
def entities(options = {})
|
@@ -211,6 +217,7 @@ module Flapjack
|
|
211
217
|
end
|
212
218
|
|
213
219
|
def set_interval_for_media(media, interval)
|
220
|
+
return if 'pagerduty'.eql?(media)
|
214
221
|
if interval.nil?
|
215
222
|
@redis.hdel("contact_media_intervals:#{self.id}", media)
|
216
223
|
return
|
@@ -225,6 +232,7 @@ module Flapjack
|
|
225
232
|
end
|
226
233
|
|
227
234
|
def set_rollup_threshold_for_media(media, threshold)
|
235
|
+
return if 'pagerduty'.eql?(media)
|
228
236
|
if threshold.nil?
|
229
237
|
@redis.hdel("contact_media_rollup_thresholds:#{self.id}", media)
|
230
238
|
return
|
@@ -234,12 +242,8 @@ module Flapjack
|
|
234
242
|
end
|
235
243
|
|
236
244
|
def set_address_for_media(media, address)
|
245
|
+
return if 'pagerduty'.eql?(media)
|
237
246
|
@redis.hset("contact_media:#{self.id}", media, address)
|
238
|
-
if media == 'pagerduty'
|
239
|
-
# FIXME - work out what to do when changing the pagerduty service key (address)
|
240
|
-
# probably best solution is to remove the need to have the username and password
|
241
|
-
# and subdomain as pagerduty's updated api's mean we don't them anymore I think...
|
242
|
-
end
|
243
247
|
self.media = @redis.hgetall("contact_media:#{@id}")
|
244
248
|
end
|
245
249
|
|
@@ -312,10 +316,13 @@ module Flapjack
|
|
312
316
|
key = "contact_alerting_checks:#{self.id}:media:#{media}"
|
313
317
|
cleaned = 0
|
314
318
|
alerting_checks_for_media(media).each do |check|
|
319
|
+
entity_check = Flapjack::Data::EntityCheck.for_event_id(check, :redis => @redis)
|
315
320
|
next unless Flapjack::Data::EntityCheck.state_for_event_id?(check, :redis => @redis) == 'ok' ||
|
316
321
|
Flapjack::Data::EntityCheck.in_unscheduled_maintenance_for_event_id?(check, :redis => @redis) ||
|
317
|
-
Flapjack::Data::EntityCheck.in_scheduled_maintenance_for_event_id?(check, :redis => @redis)
|
322
|
+
Flapjack::Data::EntityCheck.in_scheduled_maintenance_for_event_id?(check, :redis => @redis) ||
|
323
|
+
!entity_check.contacts.map {|c| c.id}.include?(self.id)
|
318
324
|
|
325
|
+
# FIXME: why can't i get this logging when called from notifier (notification.rb)?
|
319
326
|
@logger.debug("removing from alerting checks for #{self.id}/#{media}: #{check}") if @logger
|
320
327
|
remove_alerting_check_for_media(media, check)
|
321
328
|
cleaned += 1
|
@@ -30,9 +30,10 @@ module Flapjack
|
|
30
30
|
# TODO probably shouldn't always be creating on query -- work out when this should be happening
|
31
31
|
def self.for_event_id(event_id, options = {})
|
32
32
|
raise "Redis connection not set" unless redis = options[:redis]
|
33
|
+
logger = options[:logger]
|
33
34
|
entity_name, check = event_id.split(':', 2)
|
34
|
-
self.new(Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis, :create => true), check,
|
35
|
-
:redis => redis)
|
35
|
+
self.new(Flapjack::Data::Entity.find_by_name(entity_name, :redis => redis, :create => true, :logger => true), check,
|
36
|
+
:redis => redis, :logger => logger)
|
36
37
|
end
|
37
38
|
|
38
39
|
# TODO probably shouldn't always be creating on query -- work out when this should be happening
|
@@ -533,7 +534,7 @@ module Flapjack
|
|
533
534
|
end
|
534
535
|
|
535
536
|
entity.contacts + contact_ids.collect {|c_id|
|
536
|
-
Flapjack::Data::Contact.find_by_id(c_id, :redis => @redis)
|
537
|
+
Flapjack::Data::Contact.find_by_id(c_id, :redis => @redis, :logger => @logger)
|
537
538
|
}.compact
|
538
539
|
end
|
539
540
|
|
@@ -61,10 +61,8 @@ module Flapjack
|
|
61
61
|
'last_state' => last_state[:state],
|
62
62
|
'last_summary' => last_state[:summary],
|
63
63
|
'state_duration' => opts[:state_duration],
|
64
|
-
|
65
64
|
'type' => opts[:type] || type_for_event(event),
|
66
65
|
'severity' => opts[:severity],
|
67
|
-
|
68
66
|
'tags' => tag_data }
|
69
67
|
|
70
68
|
redis.rpush(queue, Oj.dump(notif))
|
@@ -94,11 +92,15 @@ module Flapjack
|
|
94
92
|
end
|
95
93
|
|
96
94
|
def ok?
|
97
|
-
@state && ['ok', 'up'].include?(@state
|
95
|
+
@state && ['ok', 'up'].include?(@state)
|
98
96
|
end
|
99
97
|
|
100
98
|
def acknowledgement?
|
101
|
-
@state && ['acknowledgement'].include?(@state
|
99
|
+
@state && ['acknowledgement'].include?(@state)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test?
|
103
|
+
@state && ['test_notifications'].include?(@state)
|
102
104
|
end
|
103
105
|
|
104
106
|
def contents
|
@@ -123,7 +125,7 @@ module Flapjack
|
|
123
125
|
default_timezone = opts[:default_timezone]
|
124
126
|
logger = opts[:logger]
|
125
127
|
|
126
|
-
@messages ||= contacts.collect
|
128
|
+
@messages ||= contacts.collect do |contact|
|
127
129
|
contact_id = contact.id
|
128
130
|
rules = contact.notification_rules
|
129
131
|
media = contact.media
|
@@ -195,36 +197,39 @@ module Flapjack
|
|
195
197
|
logger.debug "media_to_use: #{media_to_use}"
|
196
198
|
|
197
199
|
# here begins rollup madness
|
198
|
-
media_to_use.each_pair.inject([])
|
200
|
+
media_to_use.each_pair.inject([]) do |ret, (media, address)|
|
199
201
|
rollup_type = nil
|
200
202
|
|
201
|
-
contact.add_alerting_check_for_media(media, @event_id) unless ok? || acknowledgement?
|
203
|
+
contact.add_alerting_check_for_media(media, @event_id) unless ok? || acknowledgement? || test?
|
202
204
|
|
203
205
|
# expunge checks in (un)scheduled maintenance from the alerting set
|
204
206
|
cleaned = contact.clean_alerting_checks_for_media(media)
|
205
207
|
logger.debug("cleaned alerting checks for #{media}: #{cleaned}")
|
206
208
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
209
|
+
# pagerduty is an example of a medium which should never be rolled up
|
210
|
+
unless ['pagerduty'].include?(media)
|
211
|
+
alerting_checks = contact.count_alerting_checks_for_media(media)
|
212
|
+
rollup_threshold = contact.rollup_threshold_for_media(media)
|
213
|
+
case
|
214
|
+
when rollup_threshold.nil?
|
215
|
+
# back away slowly
|
216
|
+
when alerting_checks >= rollup_threshold
|
217
|
+
next ret if contact.drop_rollup_notifications_for_media?(media)
|
218
|
+
contact.update_sent_rollup_alert_keys_for_media(media, :delete => ok?)
|
219
|
+
rollup_type = 'problem'
|
220
|
+
when (alerting_checks + cleaned >= rollup_threshold)
|
221
|
+
# alerting checks was just cleaned such that it is now below the rollup threshold
|
222
|
+
rollup_type = 'recovery'
|
223
|
+
end
|
224
|
+
logger.debug "rollup decisions: #{@event_id} #{@state} #{media} #{address} rollup_type: #{rollup_type}"
|
219
225
|
end
|
220
|
-
logger.debug "rollup decisions: #{@event_id} #{@state} #{media} #{address} rollup_type: #{rollup_type}"
|
221
226
|
|
222
227
|
m = Flapjack::Data::Message.for_contact(contact,
|
223
228
|
:medium => media, :address => address, :rollup => rollup_type)
|
224
229
|
ret << m
|
225
230
|
ret
|
226
|
-
|
227
|
-
|
231
|
+
end
|
232
|
+
end.compact.flatten # @messages ||= contacts.collect do ...
|
228
233
|
end
|
229
234
|
|
230
235
|
private
|
@@ -238,16 +243,12 @@ module Flapjack
|
|
238
243
|
@time = opts['time']
|
239
244
|
@count = opts['count']
|
240
245
|
@duration = opts['duration']
|
241
|
-
|
242
246
|
@last_state = opts['last_state']
|
243
247
|
@last_summary = opts['last_summary']
|
244
248
|
@state_duration = opts['state_duration']
|
245
|
-
|
246
249
|
@type = opts['type']
|
247
250
|
@severity = opts['severity']
|
248
|
-
|
249
|
-
tags = opts['tags']
|
250
|
-
@tags = tags.is_a?(Array) ? Flapjack::Data::TagSet.new(tags) : nil
|
251
|
+
@tags = opts['tags'].is_a?(Array) ? Flapjack::Data::TagSet.new(opts['tags']) : nil
|
251
252
|
end
|
252
253
|
|
253
254
|
# # time restrictions match?
|
@@ -97,8 +97,11 @@ module Flapjack
|
|
97
97
|
# https://github.com/flpjck/flapjack/wiki/API#wiki-get_contacts
|
98
98
|
app.get '/contacts' do
|
99
99
|
content_type :json
|
100
|
-
|
101
|
-
|
100
|
+
"[" +
|
101
|
+
Flapjack::Data::Contact.all(:redis => redis).map do |contact|
|
102
|
+
contact.to_json
|
103
|
+
end.join(',') +
|
104
|
+
"]"
|
102
105
|
end
|
103
106
|
|
104
107
|
# Returns the core information about the specified contact
|
@@ -233,19 +236,36 @@ module Flapjack
|
|
233
236
|
|
234
237
|
contact = find_contact(params[:contact_id])
|
235
238
|
errors = []
|
236
|
-
if params[:address].nil?
|
237
|
-
errors << "no address for '#{params[:id]}' media"
|
238
|
-
end
|
239
239
|
|
240
|
-
|
240
|
+
if 'pagerduty'.eql?(params[:id])
|
241
|
+
errors = [:service_key, :subdomain, :username, :password].inject([]) do |memo, pdp|
|
242
|
+
memo << "no #{pdp.to_s} for 'pagerduty' media" if params[pdp].nil?
|
243
|
+
memo
|
244
|
+
end
|
245
|
+
|
246
|
+
halt err(403, *errors) unless errors.empty?
|
247
|
+
|
248
|
+
contact.set_pagerduty_credentials('service_key' => params[:service_key],
|
249
|
+
'subdomain' => params[:subdomain],
|
250
|
+
'username' => params[:username],
|
251
|
+
'password' => params[:password])
|
241
252
|
|
242
|
-
|
243
|
-
|
244
|
-
|
253
|
+
contact.pagerduty_credentials.to_json
|
254
|
+
else
|
255
|
+
if params[:address].nil?
|
256
|
+
errors << "no address for '#{params[:id]}' media"
|
257
|
+
end
|
258
|
+
|
259
|
+
halt err(403, *errors) unless errors.empty?
|
245
260
|
|
246
|
-
|
247
|
-
|
248
|
-
|
261
|
+
contact.set_address_for_media(params[:id], params[:address])
|
262
|
+
contact.set_interval_for_media(params[:id], params[:interval])
|
263
|
+
contact.set_rollup_threshold_for_media(params[:id], params[:rollup_threshold])
|
264
|
+
|
265
|
+
{'address' => contact.media[params[:id]],
|
266
|
+
'interval' => contact.media_intervals[params[:id]],
|
267
|
+
'rollup_threshold' => contact.media_rollup_thresholds[params[:id]]}.to_json
|
268
|
+
end
|
249
269
|
end
|
250
270
|
|
251
271
|
# delete a media of a contact
|
@@ -12,6 +12,7 @@ require 'em/protocols/smtpclient'
|
|
12
12
|
require 'flapjack/utility'
|
13
13
|
|
14
14
|
require 'flapjack/data/entity_check'
|
15
|
+
require 'flapjack/data/alert'
|
15
16
|
|
16
17
|
module Flapjack
|
17
18
|
module Gateways
|
@@ -31,46 +32,22 @@ module Flapjack
|
|
31
32
|
end
|
32
33
|
|
33
34
|
# TODO refactor to remove complexity
|
34
|
-
def perform(
|
35
|
-
|
36
|
-
|
35
|
+
def perform(contents)
|
36
|
+
@logger.debug "Woo, got an alert to send out: #{contents.inspect}"
|
37
|
+
alert = prepare(contents)
|
38
|
+
deliver(alert)
|
37
39
|
end
|
38
40
|
|
39
41
|
# sets a bunch of class instance variables for each email
|
40
|
-
def prepare(
|
41
|
-
|
42
|
-
|
43
|
-
# The instance variables are referenced by the templates, which
|
44
|
-
# share the current binding context
|
45
|
-
@notification_type = notification['notification_type']
|
46
|
-
@notification_id = notification['id'] || SecureRandom.uuid
|
47
|
-
@rollup = notification['rollup']
|
48
|
-
@rollup_alerts = notification['rollup_alerts']
|
49
|
-
@rollup_threshold = notification['rollup_threshold']
|
50
|
-
@contact_first_name = notification['contact_first_name']
|
51
|
-
@contact_last_name = notification['contact_last_name']
|
52
|
-
@state = notification['state']
|
53
|
-
@duration = notification['state_duration']
|
54
|
-
@summary = notification['summary']
|
55
|
-
@last_state = notification['last_state']
|
56
|
-
@last_summary = notification['last_summary']
|
57
|
-
@details = notification['details']
|
58
|
-
@time = notification['time']
|
59
|
-
@entity_name, @check = notification['event_id'].split(':', 2)
|
60
|
-
|
61
|
-
entity_check = Flapjack::Data::EntityCheck.for_event_id(notification['event_id'],
|
62
|
-
:redis => @redis)
|
63
|
-
|
64
|
-
@in_unscheduled_maintenance = entity_check.in_scheduled_maintenance?
|
65
|
-
@in_scheduled_maintenance = entity_check.in_unscheduled_maintenance?
|
66
|
-
|
42
|
+
def prepare(contents)
|
43
|
+
Flapjack::Data::Alert.new(contents, :logger => @logger)
|
67
44
|
rescue => e
|
68
|
-
@logger.error "Error preparing email to #{
|
45
|
+
@logger.error "Error preparing email to #{contents['address']}: #{e.class}: #{e.message}"
|
69
46
|
@logger.error e.backtrace.join("\n")
|
70
47
|
raise
|
71
48
|
end
|
72
49
|
|
73
|
-
def deliver(
|
50
|
+
def deliver(alert)
|
74
51
|
host = @smtp_config ? @smtp_config['host'] : nil
|
75
52
|
port = @smtp_config ? @smtp_config['port'] : nil
|
76
53
|
starttls = @smtp_config ? !! @smtp_config['starttls'] : nil
|
@@ -85,21 +62,21 @@ module Flapjack
|
|
85
62
|
|
86
63
|
m_from = "flapjack@#{@fqdn}"
|
87
64
|
@logger.debug("flapjack_mailer: set from to #{m_from}")
|
88
|
-
m_reply_to = m_from
|
89
|
-
m_to = notification['address']
|
90
|
-
|
91
65
|
|
92
|
-
mail = prepare_email(:from
|
93
|
-
:to
|
66
|
+
mail = prepare_email(:from => m_from,
|
67
|
+
:to => alert.address,
|
68
|
+
:message_id => "<#{alert.notification_id}@#{@fqdn}>",
|
69
|
+
:alert => alert)
|
94
70
|
|
95
71
|
smtp_args = {:from => m_from,
|
96
|
-
:to =>
|
72
|
+
:to => alert.address,
|
97
73
|
:content => "#{mail.to_s}\r\n.\r\n",
|
98
74
|
:domain => @fqdn,
|
99
75
|
:host => host || 'localhost',
|
100
76
|
:port => port || 25,
|
101
77
|
:starttls => starttls}
|
102
78
|
smtp_args.merge!(:auth => auth) if auth
|
79
|
+
|
103
80
|
email = EM::P::SmtpClient.send(smtp_args)
|
104
81
|
|
105
82
|
response = EM::Synchrony.sync(email)
|
@@ -107,45 +84,64 @@ module Flapjack
|
|
107
84
|
# http://tools.ietf.org/html/rfc821#page-36 SMTP response codes
|
108
85
|
if response && response.respond_to?(:code) &&
|
109
86
|
((response.code == 250) || (response.code == 251))
|
110
|
-
|
87
|
+
alert.record_send_success!
|
111
88
|
@sent += 1
|
112
89
|
else
|
113
90
|
@logger.error "Email sending failed"
|
114
91
|
end
|
115
92
|
|
116
|
-
@logger.
|
93
|
+
@logger.debug "Email response: #{response.inspect}"
|
117
94
|
|
118
95
|
rescue => e
|
119
|
-
@logger.error "Error delivering email to #{
|
96
|
+
@logger.error "Error generating or delivering email to #{alert.address}: #{e.class}: #{e.message}"
|
120
97
|
@logger.error e.backtrace.join("\n")
|
121
98
|
raise
|
122
99
|
end
|
123
100
|
|
124
101
|
private
|
125
102
|
|
103
|
+
# returns a Mail object
|
126
104
|
def prepare_email(opts = {})
|
127
105
|
from = opts[:from]
|
128
106
|
to = opts[:to]
|
129
|
-
message_id =
|
107
|
+
message_id = opts[:message_id]
|
108
|
+
alert = opts[:alert]
|
130
109
|
|
131
110
|
message_type = case
|
132
|
-
when
|
111
|
+
when alert.rollup
|
133
112
|
'rollup'
|
134
113
|
else
|
135
114
|
'alert'
|
136
115
|
end
|
137
116
|
|
138
|
-
|
139
|
-
|
117
|
+
mydir = File.dirname(__FILE__)
|
118
|
+
|
119
|
+
subject_template_path = mydir + "/email/#{message_type}_subject.text.erb"
|
120
|
+
text_template_path = mydir + "/email/#{message_type}.text.erb"
|
121
|
+
html_template_path = mydir + "/email/#{message_type}.html.erb"
|
140
122
|
|
141
|
-
|
142
|
-
|
123
|
+
subject_template = ERB.new(File.read(subject_template_path), nil, '-')
|
124
|
+
text_template = ERB.new(File.read(text_template_path), nil, '-')
|
125
|
+
html_template = ERB.new(File.read(html_template_path), nil, '-')
|
143
126
|
|
144
|
-
|
145
|
-
|
127
|
+
@alert = alert
|
128
|
+
bnd = binding
|
146
129
|
|
147
|
-
|
148
|
-
|
130
|
+
# do some intelligence gathering in case an ERB execution blows up
|
131
|
+
begin
|
132
|
+
erb_to_be_executed = subject_template_path
|
133
|
+
subject = subject_template.result(bnd).chomp
|
134
|
+
|
135
|
+
erb_to_be_executed = text_template_path
|
136
|
+
body_text = text_template.result(bnd)
|
137
|
+
|
138
|
+
erb_to_be_executed = html_template_path
|
139
|
+
body_html = html_template.result(bnd)
|
140
|
+
rescue => e
|
141
|
+
@logger.error "Error while excuting ERBs for an email: " +
|
142
|
+
"ERB being executed: #{erb_to_be_executed}"
|
143
|
+
raise
|
144
|
+
end
|
149
145
|
|
150
146
|
@logger.debug("preparing email to: #{to}, subject: #{subject}, message-id: #{message_id}")
|
151
147
|
|
@@ -157,12 +153,12 @@ module Flapjack
|
|
157
153
|
message_id message_id
|
158
154
|
|
159
155
|
text_part do
|
160
|
-
body
|
156
|
+
body body_text
|
161
157
|
end
|
162
158
|
|
163
159
|
html_part do
|
164
160
|
content_type 'text/html; charset=UTF-8'
|
165
|
-
body
|
161
|
+
body body_html
|
166
162
|
end
|
167
163
|
end
|
168
164
|
|
@@ -11,7 +11,7 @@
|
|
11
11
|
}
|
12
12
|
</style>
|
13
13
|
|
14
|
-
<p>Hi <%= @contact_first_name%></p>
|
14
|
+
<p>Hi <%= @alert.contact_first_name%></p>
|
15
15
|
|
16
16
|
<p>Monitoring has detected the following:</p>
|
17
17
|
|
@@ -19,56 +19,56 @@
|
|
19
19
|
<tbody>
|
20
20
|
<tr>
|
21
21
|
<td><strong>Entity</strong></td>
|
22
|
-
<td><%= @
|
22
|
+
<td><%= @alert.entity %></td>
|
23
23
|
</tr>
|
24
24
|
|
25
25
|
<tr>
|
26
26
|
<td><strong>Check</strong></td>
|
27
|
-
<td><%= @check %></td>
|
27
|
+
<td><%= @alert.check %></td>
|
28
28
|
</tr>
|
29
29
|
|
30
30
|
<tr>
|
31
31
|
<td><strong>State</strong></td>
|
32
|
-
<td><%=
|
32
|
+
<td><%= @alert.state_title_case %></td>
|
33
33
|
</tr>
|
34
34
|
|
35
35
|
<tr>
|
36
36
|
<td><strong>Summary</strong></td>
|
37
|
-
<td><%= @summary %></td>
|
37
|
+
<td><%= @alert.summary %></td>
|
38
38
|
</tr>
|
39
39
|
|
40
|
-
<% if @details %>
|
40
|
+
<% if @alert.details %>
|
41
41
|
<tr>
|
42
42
|
<td><strong>Details</strong></td>
|
43
|
-
<td><%= @details %></td>
|
43
|
+
<td><%= @alert.details %></td>
|
44
44
|
</tr>
|
45
45
|
<% end %>
|
46
46
|
|
47
|
-
<% if @time %>
|
47
|
+
<% if @alert.time %>
|
48
48
|
<tr>
|
49
49
|
<td><strong>Time</strong></td>
|
50
|
-
<td><%= Time.at(@time.to_i).to_s %></td>
|
50
|
+
<td><%= Time.at(@alert.time.to_i).to_s %></td>
|
51
51
|
</tr>
|
52
52
|
<% end %>
|
53
53
|
|
54
|
-
<% if @
|
54
|
+
<% if @alert.state_duration && @alert.state_duration > 40 %>
|
55
55
|
<tr>
|
56
56
|
<td><strong>Duration</strong></td>
|
57
|
-
<td><%= ChronicDuration.output(@
|
57
|
+
<td><%= ChronicDuration.output(@alert.state_duration) %></td>
|
58
58
|
</tr>
|
59
59
|
<% end %>
|
60
60
|
|
61
|
-
<% if @last_state %>
|
61
|
+
<% if @alert.last_state %>
|
62
62
|
<tr>
|
63
63
|
<td><strong>Previous State</strong></td>
|
64
|
-
<td><%=
|
64
|
+
<td><%= @alert.last_state_title_case %></td>
|
65
65
|
</tr>
|
66
66
|
<% end %>
|
67
67
|
|
68
|
-
<% if @last_summary %>
|
68
|
+
<% if @alert.last_summary %>
|
69
69
|
<tr>
|
70
70
|
<td><strong>Previous Summary</strong></td>
|
71
|
-
<td><%= @last_summary %></td>
|
71
|
+
<td><%= @alert.last_summary %></td>
|
72
72
|
</tr>
|
73
73
|
<% end %>
|
74
74
|
|