flapjack 0.7.28 → 0.7.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|