flapjack 1.6.0 → 2.0.0b1

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.
Files changed (301) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -6
  3. data/.gitmodules +1 -1
  4. data/.rspec +1 -1
  5. data/.ruby-version +1 -1
  6. data/.travis.yml +12 -13
  7. data/CHANGELOG.md +2 -9
  8. data/CONTRIBUTING.md +7 -2
  9. data/Gemfile +4 -13
  10. data/LICENCE +1 -0
  11. data/README.md +8 -2
  12. data/Rakefile +2 -2
  13. data/bin/flapjack +3 -12
  14. data/build.sh +4 -2
  15. data/etc/flapjack_config.toml.example +273 -0
  16. data/features/ack_after_sched_maint.feature +18 -21
  17. data/features/cli.feature +11 -71
  18. data/features/cli_flapjack-feed-events.feature +14 -15
  19. data/features/cli_flapjack-nagios-receiver.feature +12 -41
  20. data/features/cli_flapper.feature +12 -41
  21. data/features/cli_purge.feature +5 -6
  22. data/features/cli_receive-events.feature +6 -7
  23. data/features/cli_simulate-failed-check.feature +5 -6
  24. data/features/events.feature +206 -181
  25. data/features/events_check_names.feature +4 -7
  26. data/features/notification_rules.feature +144 -223
  27. data/features/notifications.feature +65 -57
  28. data/features/rollup.feature +45 -47
  29. data/features/steps/cli_steps.rb +4 -5
  30. data/features/steps/events_steps.rb +163 -373
  31. data/features/steps/notifications_steps.rb +408 -264
  32. data/features/steps/packaging-lintian_steps.rb +0 -4
  33. data/features/steps/time_travel_steps.rb +0 -26
  34. data/features/support/daemons.rb +6 -31
  35. data/features/support/env.rb +65 -74
  36. data/flapjack.gemspec +22 -24
  37. data/lib/flapjack.rb +14 -7
  38. data/lib/flapjack/cli/flapper.rb +74 -173
  39. data/lib/flapjack/cli/maintenance.rb +278 -109
  40. data/lib/flapjack/cli/migrate.rb +950 -0
  41. data/lib/flapjack/cli/purge.rb +19 -22
  42. data/lib/flapjack/cli/receiver.rb +150 -326
  43. data/lib/flapjack/cli/server.rb +8 -235
  44. data/lib/flapjack/cli/simulate.rb +42 -57
  45. data/lib/flapjack/configuration.rb +51 -37
  46. data/lib/flapjack/coordinator.rb +138 -129
  47. data/lib/flapjack/data/acknowledgement.rb +177 -0
  48. data/lib/flapjack/data/alert.rb +97 -158
  49. data/lib/flapjack/data/check.rb +611 -0
  50. data/lib/flapjack/data/condition.rb +70 -0
  51. data/lib/flapjack/data/contact.rb +226 -456
  52. data/lib/flapjack/data/event.rb +96 -184
  53. data/lib/flapjack/data/extensions/associations.rb +59 -0
  54. data/lib/flapjack/data/extensions/short_name.rb +25 -0
  55. data/lib/flapjack/data/medium.rb +428 -0
  56. data/lib/flapjack/data/metrics.rb +194 -0
  57. data/lib/flapjack/data/notification.rb +22 -281
  58. data/lib/flapjack/data/rule.rb +473 -0
  59. data/lib/flapjack/data/scheduled_maintenance.rb +244 -0
  60. data/lib/flapjack/data/state.rb +221 -0
  61. data/lib/flapjack/data/statistic.rb +112 -0
  62. data/lib/flapjack/data/tag.rb +277 -0
  63. data/lib/flapjack/data/test_notification.rb +182 -0
  64. data/lib/flapjack/data/unscheduled_maintenance.rb +159 -0
  65. data/lib/flapjack/data/validators/id_validator.rb +20 -0
  66. data/lib/flapjack/exceptions.rb +6 -0
  67. data/lib/flapjack/filters/acknowledgement.rb +23 -16
  68. data/lib/flapjack/filters/base.rb +0 -5
  69. data/lib/flapjack/filters/delays.rb +53 -43
  70. data/lib/flapjack/filters/ok.rb +23 -14
  71. data/lib/flapjack/filters/scheduled_maintenance.rb +3 -3
  72. data/lib/flapjack/filters/unscheduled_maintenance.rb +12 -3
  73. data/lib/flapjack/gateways/aws_sns.rb +65 -49
  74. data/lib/flapjack/gateways/aws_sns/alert.text.erb +2 -2
  75. data/lib/flapjack/gateways/aws_sns/alert_subject.text.erb +2 -2
  76. data/lib/flapjack/gateways/aws_sns/rollup_subject.text.erb +1 -1
  77. data/lib/flapjack/gateways/email.rb +107 -90
  78. data/lib/flapjack/gateways/email/alert.html.erb +19 -18
  79. data/lib/flapjack/gateways/email/alert.text.erb +20 -14
  80. data/lib/flapjack/gateways/email/alert_subject.text.erb +2 -1
  81. data/lib/flapjack/gateways/email/rollup.html.erb +14 -13
  82. data/lib/flapjack/gateways/email/rollup.text.erb +13 -10
  83. data/lib/flapjack/gateways/jabber.rb +679 -671
  84. data/lib/flapjack/gateways/jabber/alert.text.erb +9 -6
  85. data/lib/flapjack/gateways/jsonapi.rb +164 -350
  86. data/lib/flapjack/gateways/jsonapi/data/join_descriptor.rb +44 -0
  87. data/lib/flapjack/gateways/jsonapi/data/method_descriptor.rb +21 -0
  88. data/lib/flapjack/gateways/jsonapi/helpers/headers.rb +63 -0
  89. data/lib/flapjack/gateways/jsonapi/helpers/miscellaneous.rb +136 -0
  90. data/lib/flapjack/gateways/jsonapi/helpers/resources.rb +227 -0
  91. data/lib/flapjack/gateways/jsonapi/helpers/serialiser.rb +313 -0
  92. data/lib/flapjack/gateways/jsonapi/helpers/swagger_docs.rb +322 -0
  93. data/lib/flapjack/gateways/jsonapi/methods/association_delete.rb +115 -0
  94. data/lib/flapjack/gateways/jsonapi/methods/association_get.rb +288 -0
  95. data/lib/flapjack/gateways/jsonapi/methods/association_patch.rb +178 -0
  96. data/lib/flapjack/gateways/jsonapi/methods/association_post.rb +116 -0
  97. data/lib/flapjack/gateways/jsonapi/methods/metrics.rb +71 -0
  98. data/lib/flapjack/gateways/jsonapi/methods/resource_delete.rb +119 -0
  99. data/lib/flapjack/gateways/jsonapi/methods/resource_get.rb +186 -0
  100. data/lib/flapjack/gateways/jsonapi/methods/resource_patch.rb +239 -0
  101. data/lib/flapjack/gateways/jsonapi/methods/resource_post.rb +197 -0
  102. data/lib/flapjack/gateways/jsonapi/middleware/array_param_fixer.rb +27 -0
  103. data/lib/flapjack/gateways/jsonapi/{rack → middleware}/json_params_parser.rb +7 -6
  104. data/lib/flapjack/gateways/jsonapi/middleware/request_timestamp.rb +18 -0
  105. data/lib/flapjack/gateways/oobetet.rb +222 -170
  106. data/lib/flapjack/gateways/pager_duty.rb +388 -0
  107. data/lib/flapjack/gateways/pager_duty/alert.text.erb +13 -0
  108. data/lib/flapjack/gateways/slack.rb +56 -48
  109. data/lib/flapjack/gateways/slack/alert.text.erb +1 -1
  110. data/lib/flapjack/gateways/slack/rollup.text.erb +1 -1
  111. data/lib/flapjack/gateways/sms_aspsms.rb +155 -0
  112. data/lib/flapjack/gateways/sms_aspsms/alert.text.erb +7 -0
  113. data/lib/flapjack/gateways/sms_aspsms/rollup.text.erb +2 -0
  114. data/lib/flapjack/gateways/sms_messagenet.rb +77 -57
  115. data/lib/flapjack/gateways/sms_messagenet/alert.text.erb +3 -2
  116. data/lib/flapjack/gateways/sms_nexmo.rb +53 -51
  117. data/lib/flapjack/gateways/sms_nexmo/alert.text.erb +2 -2
  118. data/lib/flapjack/gateways/sms_nexmo/rollup.text.erb +1 -1
  119. data/lib/flapjack/gateways/sms_twilio.rb +79 -62
  120. data/lib/flapjack/gateways/sms_twilio/alert.text.erb +3 -2
  121. data/lib/flapjack/gateways/web.rb +437 -345
  122. data/lib/flapjack/gateways/web/middleware/request_timestamp.rb +18 -0
  123. data/lib/flapjack/gateways/web/public/css/bootstrap.css +3793 -4340
  124. data/lib/flapjack/gateways/web/public/css/bootstrap.css.map +1 -0
  125. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.eot +0 -0
  126. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.svg +273 -214
  127. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  128. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff +0 -0
  129. data/lib/flapjack/gateways/web/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  130. data/lib/flapjack/gateways/web/public/js/bootstrap.js +1637 -1607
  131. data/lib/flapjack/gateways/web/public/js/self_stats.js +1 -2
  132. data/lib/flapjack/gateways/web/views/_pagination.html.erb +19 -0
  133. data/lib/flapjack/gateways/web/views/check.html.erb +159 -121
  134. data/lib/flapjack/gateways/web/views/checks.html.erb +82 -41
  135. data/lib/flapjack/gateways/web/views/contact.html.erb +59 -71
  136. data/lib/flapjack/gateways/web/views/contacts.html.erb +32 -8
  137. data/lib/flapjack/gateways/web/views/index.html.erb +2 -2
  138. data/lib/flapjack/gateways/web/views/{layout.erb → layout.html.erb} +7 -23
  139. data/lib/flapjack/gateways/web/views/self_stats.html.erb +32 -33
  140. data/lib/flapjack/gateways/web/views/tag.html.erb +32 -0
  141. data/lib/flapjack/gateways/web/views/tags.html.erb +51 -0
  142. data/lib/flapjack/logger.rb +34 -3
  143. data/lib/flapjack/notifier.rb +180 -112
  144. data/lib/flapjack/patches.rb +8 -63
  145. data/lib/flapjack/pikelet.rb +185 -143
  146. data/lib/flapjack/processor.rb +323 -191
  147. data/lib/flapjack/record_queue.rb +33 -0
  148. data/lib/flapjack/redis_proxy.rb +66 -0
  149. data/lib/flapjack/utility.rb +21 -15
  150. data/lib/flapjack/version.rb +2 -1
  151. data/libexec/httpbroker.go +218 -14
  152. data/libexec/oneoff.go +13 -10
  153. data/spec/lib/flapjack/configuration_spec.rb +286 -0
  154. data/spec/lib/flapjack/coordinator_spec.rb +103 -157
  155. data/spec/lib/flapjack/data/check_spec.rb +175 -0
  156. data/spec/lib/flapjack/data/contact_spec.rb +26 -349
  157. data/spec/lib/flapjack/data/event_spec.rb +76 -291
  158. data/spec/lib/flapjack/data/medium_spec.rb +19 -0
  159. data/spec/lib/flapjack/data/rule_spec.rb +43 -0
  160. data/spec/lib/flapjack/data/scheduled_maintenance_spec.rb +976 -0
  161. data/spec/lib/flapjack/data/unscheduled_maintenance_spec.rb +34 -0
  162. data/spec/lib/flapjack/gateways/aws_sns_spec.rb +111 -60
  163. data/spec/lib/flapjack/gateways/email_spec.rb +194 -161
  164. data/spec/lib/flapjack/gateways/jabber_spec.rb +961 -162
  165. data/spec/lib/flapjack/gateways/jsonapi/methods/check_links_spec.rb +155 -0
  166. data/spec/lib/flapjack/gateways/jsonapi/methods/checks_spec.rb +426 -0
  167. data/spec/lib/flapjack/gateways/jsonapi/methods/contact_links_spec.rb +217 -0
  168. data/spec/lib/flapjack/gateways/jsonapi/methods/contacts_spec.rb +425 -0
  169. data/spec/lib/flapjack/gateways/jsonapi/methods/events_spec.rb +271 -0
  170. data/spec/lib/flapjack/gateways/jsonapi/methods/media_spec.rb +257 -0
  171. data/spec/lib/flapjack/gateways/jsonapi/methods/medium_links_spec.rb +163 -0
  172. data/spec/lib/flapjack/gateways/jsonapi/methods/metrics_spec.rb +8 -0
  173. data/spec/lib/flapjack/gateways/jsonapi/methods/rule_links_spec.rb +212 -0
  174. data/spec/lib/flapjack/gateways/jsonapi/methods/rules_spec.rb +289 -0
  175. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenance_links_spec.rb +49 -0
  176. data/spec/lib/flapjack/gateways/jsonapi/methods/scheduled_maintenances_spec.rb +242 -0
  177. data/spec/lib/flapjack/gateways/jsonapi/methods/tag_links_spec.rb +274 -0
  178. data/spec/lib/flapjack/gateways/jsonapi/methods/tags_spec.rb +302 -0
  179. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenance_links_spec.rb +49 -0
  180. data/spec/lib/flapjack/gateways/jsonapi/methods/unscheduled_maintenances_spec.rb +339 -0
  181. data/spec/lib/flapjack/gateways/jsonapi_spec.rb +1 -1
  182. data/spec/lib/flapjack/gateways/oobetet_spec.rb +151 -79
  183. data/spec/lib/flapjack/gateways/pager_duty_spec.rb +353 -0
  184. data/spec/lib/flapjack/gateways/slack_spec.rb +53 -53
  185. data/spec/lib/flapjack/gateways/sms_aspsms_spec.rb +106 -0
  186. data/spec/lib/flapjack/gateways/sms_messagenet_spec.rb +111 -54
  187. data/spec/lib/flapjack/gateways/sms_nexmo_spec.rb +50 -51
  188. data/spec/lib/flapjack/gateways/sms_twilio_spec.rb +108 -48
  189. data/spec/lib/flapjack/gateways/web_spec.rb +144 -216
  190. data/spec/lib/flapjack/notifier_spec.rb +132 -1
  191. data/spec/lib/flapjack/pikelet_spec.rb +111 -50
  192. data/spec/lib/flapjack/processor_spec.rb +210 -40
  193. data/spec/lib/flapjack/redis_proxy_spec.rb +45 -0
  194. data/spec/lib/flapjack/utility_spec.rb +11 -15
  195. data/spec/service_consumers/fixture_data.rb +547 -0
  196. data/spec/service_consumers/pact_helper.rb +21 -32
  197. data/spec/service_consumers/pacts/flapjack-diner_v2.0.json +4652 -0
  198. data/spec/service_consumers/provider_states_for_flapjack-diner.rb +279 -322
  199. data/spec/service_consumers/provider_support.rb +8 -0
  200. data/spec/spec_helper.rb +34 -44
  201. data/spec/support/erb_view_helper.rb +1 -1
  202. data/spec/support/factories.rb +58 -0
  203. data/spec/support/jsonapi_helper.rb +15 -26
  204. data/spec/support/mock_logger.rb +43 -0
  205. data/spec/support/xmpp_comparable.rb +24 -0
  206. data/src/flapjack/transport_test.go +30 -1
  207. data/tasks/dump_keys.rake +82 -0
  208. data/tasks/events.rake +7 -7
  209. data/tasks/support/flapjack_config_benchmark.toml +28 -0
  210. data/tasks/support/flapjack_config_benchmark.yaml +0 -2
  211. metadata +175 -222
  212. data/Guardfile +0 -14
  213. data/etc/flapjack_config.yaml.example +0 -477
  214. data/features/cli_flapjack-populator.feature +0 -90
  215. data/features/support/silent_system.rb +0 -4
  216. data/lib/flapjack/cli/import.rb +0 -108
  217. data/lib/flapjack/data/entity.rb +0 -652
  218. data/lib/flapjack/data/entity_check.rb +0 -1044
  219. data/lib/flapjack/data/message.rb +0 -56
  220. data/lib/flapjack/data/migration.rb +0 -234
  221. data/lib/flapjack/data/notification_rule.rb +0 -425
  222. data/lib/flapjack/data/semaphore.rb +0 -44
  223. data/lib/flapjack/data/tagged.rb +0 -48
  224. data/lib/flapjack/gateways/jsonapi/check_methods.rb +0 -206
  225. data/lib/flapjack/gateways/jsonapi/check_presenter.rb +0 -221
  226. data/lib/flapjack/gateways/jsonapi/contact_methods.rb +0 -186
  227. data/lib/flapjack/gateways/jsonapi/entity_methods.rb +0 -223
  228. data/lib/flapjack/gateways/jsonapi/medium_methods.rb +0 -185
  229. data/lib/flapjack/gateways/jsonapi/metrics_methods.rb +0 -132
  230. data/lib/flapjack/gateways/jsonapi/notification_rule_methods.rb +0 -141
  231. data/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods.rb +0 -139
  232. data/lib/flapjack/gateways/jsonapi/report_methods.rb +0 -146
  233. data/lib/flapjack/gateways/pagerduty.rb +0 -318
  234. data/lib/flapjack/gateways/pagerduty/alert.text.erb +0 -10
  235. data/lib/flapjack/gateways/web/public/css/select2-bootstrap.css +0 -87
  236. data/lib/flapjack/gateways/web/public/css/select2.css +0 -615
  237. data/lib/flapjack/gateways/web/public/css/tablesort.css +0 -67
  238. data/lib/flapjack/gateways/web/public/img/select2-spinner.gif +0 -0
  239. data/lib/flapjack/gateways/web/public/img/select2.png +0 -0
  240. data/lib/flapjack/gateways/web/public/img/select2x2.png +0 -0
  241. data/lib/flapjack/gateways/web/public/js/backbone.js +0 -1581
  242. data/lib/flapjack/gateways/web/public/js/backbone.jsonapi.js +0 -322
  243. data/lib/flapjack/gateways/web/public/js/flapjack.js +0 -82
  244. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.js +0 -1640
  245. data/lib/flapjack/gateways/web/public/js/jquery.tablesorter.widgets.js +0 -1390
  246. data/lib/flapjack/gateways/web/public/js/modules/contact.js +0 -520
  247. data/lib/flapjack/gateways/web/public/js/modules/entity.js +0 -28
  248. data/lib/flapjack/gateways/web/public/js/modules/medium.js +0 -40
  249. data/lib/flapjack/gateways/web/public/js/select2.js +0 -3397
  250. data/lib/flapjack/gateways/web/public/js/tablesort.js +0 -44
  251. data/lib/flapjack/gateways/web/public/js/underscore.js +0 -1276
  252. data/lib/flapjack/gateways/web/views/edit_contacts.html.erb +0 -173
  253. data/lib/flapjack/gateways/web/views/entities.html.erb +0 -30
  254. data/lib/flapjack/gateways/web/views/entity.html.erb +0 -51
  255. data/lib/flapjack/rack_logger.rb +0 -47
  256. data/lib/flapjack/redis_pool.rb +0 -42
  257. data/spec/lib/flapjack/data/entity_check_spec.rb +0 -1418
  258. data/spec/lib/flapjack/data/entity_spec.rb +0 -872
  259. data/spec/lib/flapjack/data/message_spec.rb +0 -30
  260. data/spec/lib/flapjack/data/migration_spec.rb +0 -104
  261. data/spec/lib/flapjack/data/notification_rule_spec.rb +0 -232
  262. data/spec/lib/flapjack/data/notification_spec.rb +0 -53
  263. data/spec/lib/flapjack/data/semaphore_spec.rb +0 -24
  264. data/spec/lib/flapjack/filters/acknowledgement_spec.rb +0 -6
  265. data/spec/lib/flapjack/filters/delays_spec.rb +0 -6
  266. data/spec/lib/flapjack/filters/ok_spec.rb +0 -6
  267. data/spec/lib/flapjack/filters/scheduled_maintenance_spec.rb +0 -6
  268. data/spec/lib/flapjack/filters/unscheduled_maintenance_spec.rb +0 -6
  269. data/spec/lib/flapjack/gateways/jsonapi/check_methods_spec.rb +0 -315
  270. data/spec/lib/flapjack/gateways/jsonapi/check_presenter_spec.rb +0 -223
  271. data/spec/lib/flapjack/gateways/jsonapi/contact_methods_spec.rb +0 -131
  272. data/spec/lib/flapjack/gateways/jsonapi/entity_methods_spec.rb +0 -389
  273. data/spec/lib/flapjack/gateways/jsonapi/medium_methods_spec.rb +0 -231
  274. data/spec/lib/flapjack/gateways/jsonapi/notification_rule_methods_spec.rb +0 -169
  275. data/spec/lib/flapjack/gateways/jsonapi/pagerduty_credential_methods_spec.rb +0 -114
  276. data/spec/lib/flapjack/gateways/jsonapi/report_methods_spec.rb +0 -590
  277. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +0 -249
  278. data/spec/lib/flapjack/gateways/web/views/check.html.erb_spec.rb +0 -21
  279. data/spec/lib/flapjack/gateways/web/views/contact.html.erb_spec.rb +0 -24
  280. data/spec/lib/flapjack/gateways/web/views/index.html.erb_spec.rb +0 -16
  281. data/spec/lib/flapjack/redis_pool_spec.rb +0 -29
  282. data/spec/service_consumers/pacts/flapjack-diner_v1.0.json +0 -4702
  283. data/tasks/entities.rake +0 -151
  284. data/tasks/profile.rake +0 -282
  285. data/tmp/acknowledge.rb +0 -13
  286. data/tmp/create_config_yaml.rb +0 -16
  287. data/tmp/create_event_ok.rb +0 -30
  288. data/tmp/create_event_unknown.rb +0 -30
  289. data/tmp/create_events_failure.rb +0 -34
  290. data/tmp/create_events_ok.rb +0 -32
  291. data/tmp/create_events_ok_fail_ack_ok.rb +0 -53
  292. data/tmp/create_events_ok_failure.rb +0 -41
  293. data/tmp/create_events_ok_failure_ack.rb +0 -53
  294. data/tmp/dummy_contacts.json +0 -43
  295. data/tmp/dummy_entities.json +0 -37
  296. data/tmp/generate_nagios_test_hosts.rb +0 -16
  297. data/tmp/notification_rules.rb +0 -73
  298. data/tmp/parse_config_yaml.rb +0 -7
  299. data/tmp/redis_find_spurious_unknown_states.rb +0 -52
  300. data/tmp/test_json_post.rb +0 -19
  301. data/tmp/test_notification_rules_api.rb +0 -171
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'chronic_duration'
4
4
 
5
- require 'em-hiredis'
5
+ require 'flapjack/redis_proxy'
6
6
 
7
7
  require 'flapjack/filters/acknowledgement'
8
8
  require 'flapjack/filters/ok'
@@ -10,9 +10,12 @@ require 'flapjack/filters/scheduled_maintenance'
10
10
  require 'flapjack/filters/unscheduled_maintenance'
11
11
  require 'flapjack/filters/delays'
12
12
 
13
- require 'flapjack/data/entity_check'
13
+ require 'flapjack/data/check'
14
14
  require 'flapjack/data/event'
15
- require 'flapjack/redis_pool'
15
+ require 'flapjack/data/notification'
16
+ require 'flapjack/data/statistic'
17
+
18
+ require 'flapjack/exceptions'
16
19
  require 'flapjack/utility'
17
20
 
18
21
  module Flapjack
@@ -22,15 +25,26 @@ module Flapjack
22
25
  include Flapjack::Utility
23
26
 
24
27
  def initialize(opts = {})
28
+ @lock = opts[:lock]
29
+
25
30
  @config = opts[:config]
26
- @redis_config = opts[:redis_config] || {}
27
- @logger = opts[:logger]
28
31
 
29
- @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger)
32
+ @boot_time = opts[:boot_time]
30
33
 
31
34
  @queue = @config['queue'] || 'events'
32
35
 
33
- @notifier_queue = @config['notifier_queue'] || 'notifications'
36
+ @initial_failure_delay = @config['initial_failure_delay']
37
+ if !@initial_failure_delay.is_a?(Integer) || (@initial_failure_delay < 0)
38
+ @initial_failure_delay = nil
39
+ end
40
+
41
+ @repeat_failure_delay = @config['repeat_failure_delay']
42
+ if !@repeat_failure_delay.is_a?(Integer) || (@repeat_failure_delay < 0)
43
+ @repeat_failure_delay = nil
44
+ end
45
+
46
+ @notifier_queue = Flapjack::RecordQueue.new(@config['notifier_queue'] || 'notifications',
47
+ Flapjack::Data::Notification)
34
48
 
35
49
  @archive_events = @config['archive_events'] || false
36
50
  @events_archive_maxage = @config['events_archive_maxage']
@@ -38,248 +52,366 @@ module Flapjack
38
52
  ncsm_duration_conf = @config['new_check_scheduled_maintenance_duration'] || '100 years'
39
53
  @ncsm_duration = ChronicDuration.parse(ncsm_duration_conf, :keep_zero => true)
40
54
 
41
- @ncsm_ignore_tags = @config['new_check_scheduled_maintenance_ignore_tags'] || []
55
+ ncsm_ignore = @config['new_check_scheduled_maintenance_ignore_regex']
56
+ @ncsm_ignore_regex = if ncsm_ignore.nil? || ncsm_ignore.strip.empty?
57
+ nil
58
+ else
59
+ Regexp.new(ncsm_ignore)
60
+ end
42
61
 
43
- @exit_on_queue_empty = !! @config['exit_on_queue_empty']
62
+ @exit_on_queue_empty = !!@config['exit_on_queue_empty']
44
63
 
45
- options = { :logger => opts[:logger], :redis => @redis }
46
- @filters = []
47
- @filters << Flapjack::Filters::Ok.new(options)
48
- @filters << Flapjack::Filters::ScheduledMaintenance.new(options)
49
- @filters << Flapjack::Filters::UnscheduledMaintenance.new(options)
50
- @filters << Flapjack::Filters::Delays.new(options)
51
- @filters << Flapjack::Filters::Acknowledgement.new(options)
64
+ @filters = [Flapjack::Filters::Ok.new,
65
+ Flapjack::Filters::ScheduledMaintenance.new,
66
+ Flapjack::Filters::UnscheduledMaintenance.new,
67
+ Flapjack::Filters::Delays.new,
68
+ Flapjack::Filters::Acknowledgement.new]
52
69
 
53
- boot_time = opts[:boot_time]
54
70
  fqdn = `/bin/hostname -f`.chomp
55
71
  pid = Process.pid
56
72
  @instance_id = "#{fqdn}:#{pid}"
57
-
58
- # FIXME: all of the below keys assume there is only ever one executive running;
59
- # we could generate a fuid and save it to disk, and prepend it from that
60
- # point on...
61
-
62
- # FIXME: add an administrative function to reset all event counters
63
-
64
- @redis.hset('event_counters', 'all', 0) if @redis.hget('event_counters', 'all').nil?
65
- @redis.hset('event_counters', 'ok', 0) if @redis.hget('event_counters', 'ok').nil?
66
- @redis.hset('event_counters', 'failure', 0) if @redis.hget('event_counters', 'failure').nil?
67
- @redis.hset('event_counters', 'action', 0) if @redis.hget('event_counters', 'action').nil?
68
- @redis.hset('event_counters', 'invalid', 0) if @redis.hget('event_counters', 'invalid').nil?
69
-
70
- @redis.hset("executive_instance:#{@instance_id}", 'boot_time', boot_time.to_i)
71
- @redis.hset("event_counters:#{@instance_id}", 'all', 0)
72
- @redis.hset("event_counters:#{@instance_id}", 'ok', 0)
73
- @redis.hset("event_counters:#{@instance_id}", 'failure', 0)
74
- @redis.hset("event_counters:#{@instance_id}", 'action', 0)
75
- @redis.hset("event_counters:#{@instance_id}", 'invalid', 0)
76
- touch_keys
77
73
  end
78
74
 
79
- # expire instance keys after one week
80
- # TODO: set up a separate EM timer to reset key expiry every minute
81
- # and reduce the expiry to, say, five minutes
82
- # TODO: remove these keys on process exit
83
- def touch_keys
84
- [ "executive_instance:#{@instance_id}",
85
- "event_counters:#{@instance_id}",
86
- "event_counters:#{@instance_id}",
87
- "event_counters:#{@instance_id}",
88
- "event_counters:#{@instance_id}" ].each {|key|
89
- @redis.expire(key, 1036800)
90
- }
75
+ def start_stats
76
+ empty_stats = {:created_at => @boot_time, :all_events => 0,
77
+ :ok_events => 0, :failure_events => 0, :action_events => 0,
78
+ :invalid_events => 0}
79
+
80
+ @global_stats = Flapjack::Data::Statistic.
81
+ intersect(:instance_name => 'global').all.first
82
+
83
+ if @global_stats.nil?
84
+ @global_stats = Flapjack::Data::Statistic.new(empty_stats.merge(
85
+ :instance_name => 'global'))
86
+ @global_stats.save!
87
+ end
88
+
89
+ @instance_stats = Flapjack::Data::Statistic.new(empty_stats.merge(
90
+ :instance_name => @instance_id))
91
+ @instance_stats.save!
91
92
  end
92
93
 
93
94
  def start
94
- @logger.info("Booting main loop.")
95
-
96
- until @should_quit
97
- @logger.debug("Waiting for event...")
98
- event = Flapjack::Data::Event.next(@queue,
99
- :redis => @redis,
100
- :archive_events => @archive_events,
101
- :events_archive_maxage => @events_archive_maxage,
102
- :logger => @logger,
103
- :block => ! @exit_on_queue_empty )
104
- if @exit_on_queue_empty && event.nil? && Flapjack::Data::Event.pending_count(@queue, :redis => @redis)
105
- # SHUT IT ALL DOWN!!!
106
- @logger.warn "Shutting down as exit_on_queue_empty is true, and the queue is empty"
107
- Process.kill('INT', Process.pid)
108
- break
109
- end
95
+ Flapjack.logger.info("Booting main loop.")
110
96
 
111
- if event.nil?
112
- @redis.hincrby('event_counters', 'all', 1)
113
- @redis.hincrby("event_counters:#{@instance_id}", 'all', 1)
114
- @redis.hincrby('event_counters', 'invalid', 1)
115
- @redis.hincrby("event_counters:#{@instance_id}", 'invalid', 1)
116
- else
117
- process_event(event)
97
+ begin
98
+ Zermelo.redis = Flapjack.redis
99
+
100
+ start_stats
101
+
102
+ queue = (@config['queue'] || 'events')
103
+
104
+ loop do
105
+ @lock.synchronize do
106
+ foreach_on_queue(queue) {|event| process_event(event)}
107
+ end
108
+
109
+ raise Flapjack::GlobalStop if @exit_on_queue_empty
110
+
111
+ wait_for_queue(queue)
118
112
  end
113
+
114
+ ensure
115
+ @instance_stats.destroy unless @instance_stats.nil? || !@instance_stats.persisted?
116
+ Flapjack.redis.quit
119
117
  end
118
+ end
120
119
 
121
- @logger.info("Exiting main loop.")
120
+ def stop_type
121
+ :exception
122
122
  end
123
123
 
124
- # this must use a separate connection to the main Executive one, as it's running
125
- # from a different fiber while the main one is blocking.
126
- def stop
127
- unless @should_quit
128
- @should_quit = true
129
- redis_uri = @redis_config[:path] ||
130
- "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
131
- shutdown_redis = EM::Hiredis.connect(redis_uri)
132
- shutdown_redis.rpush('events', Flapjack.dump_json('type' => 'noop'))
124
+ private
125
+
126
+ def foreach_on_queue(queue, opts = {})
127
+ base_time_str = Time.now.utc.strftime "%Y%m%d%H"
128
+ rejects = "events_rejected:#{base_time_str}"
129
+ archive = @archive_events ? "events_archive:#{base_time_str}" : nil
130
+ max_age = archive ? @events_archive_maxage : nil
131
+
132
+ while event_json = (archive ? Flapjack.redis.rpoplpush(queue, archive) :
133
+ Flapjack.redis.rpop(queue))
134
+ parsed, errors = Flapjack::Data::Event.parse_and_validate(event_json)
135
+ if !errors.nil? && !errors.empty?
136
+ Flapjack.redis.multi do |multi|
137
+ if archive
138
+ multi.lrem(archive, 1, event_json)
139
+ end
140
+ multi.lpush(rejects, event_json)
141
+ @global_stats.all_events += 1
142
+ @global_stats.invalid_events += 1
143
+ @instance_stats.all_events += 1
144
+ @instance_stats.invalid_events += 1
145
+ if archive
146
+ multi.expire(archive, max_age)
147
+ end
148
+ end
149
+ Flapjack::Data::Statistic.lock do
150
+ @global_stats.save!
151
+ @instance_stats.save!
152
+ end
153
+ Flapjack.logger.error {
154
+ error_str = errors.nil? ? '' : errors.join(', ')
155
+ "Invalid event data received, #{error_str} #{parsed.inspect}"
156
+ }
157
+ else
158
+ Flapjack.redis.expire(archive, max_age) if archive
159
+ yield Flapjack::Data::Event.new(parsed) if block_given?
160
+ end
133
161
  end
134
162
  end
135
163
 
136
- private
164
+ def wait_for_queue(queue)
165
+ Flapjack.redis.brpop("#{queue}_actions")
166
+ end
137
167
 
138
168
  def process_event(event)
139
- pending = Flapjack::Data::Event.pending_count(@queue, :redis => @redis)
140
- @logger.debug("#{pending} events waiting on the queue")
141
- @logger.debug("Raw event received: #{event.inspect}")
142
-
143
- if ('noop' == event.type)
144
- return
169
+ Flapjack.logger.debug {
170
+ pending = Flapjack::Data::Event.pending_count(@queue)
171
+ "#{pending} events waiting on the queue"
172
+ }
173
+ Flapjack.logger.debug { "Event received: #{event.inspect}" }
174
+ Flapjack.logger.debug { "Processing Event: #{event.dump}" }
175
+
176
+ timestamp = Time.now
177
+
178
+ event_condition = case event.state
179
+ when 'acknowledgement', /\Atest_notifications(?:\s+#{Flapjack::Data::Condition.unhealthy.keys.join('|')})?\z/
180
+ nil
181
+ else
182
+ cond = Flapjack::Data::Condition.for_name(event.state)
183
+ if cond.nil?
184
+ Flapjack.logger.error { "Invalid event received: #{event.inspect}" }
185
+ Flapjack::Data::Statistic.lock do
186
+ @global_stats.all_events += 1
187
+ @global_stats.invalid_events += 1
188
+ @instance_stats.all_events += 1
189
+ @instance_stats.invalid_events += 1
190
+ @global_stats.save!
191
+ @instance_stats.save!
192
+ end
193
+ return
194
+ end
195
+ cond
145
196
  end
146
197
 
147
- event_str = "#{event.id}, #{event.type}, #{event.state}, #{event.summary}"
148
- event_str << ", #{Time.at(event.time).to_s}" if event.time
149
- @logger.debug("Processing Event: #{event_str}")
198
+ Flapjack::Data::Check.lock(Flapjack::Data::State,
199
+ Flapjack::Data::ScheduledMaintenance, Flapjack::Data::UnscheduledMaintenance,
200
+ Flapjack::Data::Tag,
201
+ # Flapjack::Data::Route,
202
+ Flapjack::Data::Medium,
203
+ Flapjack::Data::Notification, Flapjack::Data::Statistic) do
150
204
 
151
- entity_check = Flapjack::Data::EntityCheck.for_event_id(event.id, :create_entity => true, :redis => @redis)
152
- timestamp = Time.now.to_i
205
+ check = Flapjack::Data::Check.intersect(:name => event.id).all.first ||
206
+ Flapjack::Data::Check.new(:name => event.id)
153
207
 
154
- event.tags = (event.tags || Set.new) + entity_check.tags
208
+ # result will be nil if check has been created via API but has no events
209
+ old_state = check.id.nil? ? nil : check.states.first
155
210
 
156
- should_notify, previous_state = update_keys(event, entity_check, timestamp)
211
+ # NB new_state won't be saved unless;
212
+ # * the condition differs from old_state (goes into history); or
213
+ # * it's being used for a notification (attach to medium, notification)
214
+ new_state = Flapjack::Data::State.new(:created_at => timestamp,
215
+ :updated_at => timestamp)
157
216
 
158
- if !should_notify
159
- @logger.debug("Not generating notification for event #{event.id} because filtering was skipped")
160
- return
161
- elsif blocker = @filters.find {|filter| filter.block?(event, entity_check, previous_state) }
162
- @logger.debug("Not generating notification for event #{event.id} because this filter blocked: #{blocker.name}")
163
- return
164
- end
217
+ update_check(check, old_state, new_state, event, event_condition,
218
+ timestamp)
165
219
 
166
- @logger.info("Generating notification for event #{event_str}")
167
- generate_notification(event, entity_check, timestamp, previous_state)
168
- end
220
+ check.enabled = true unless event_condition.nil?
169
221
 
170
- def update_keys(event, entity_check, timestamp)
171
- # TODO: run touch_keys from a separate EM timer for efficiency
172
- touch_keys
222
+ ncsm_sched_maint = nil
223
+ if check.id.nil? && (@ncsm_duration > 0) && (@ncsm_ignore_regex.nil? ||
224
+ @ncsm_ignore_regex.match(check.name).nil?)
173
225
 
174
- result = true
175
- previous_state = nil
226
+ Flapjack.logger.info { "Setting scheduled maintenance for #{time_period_in_words(@ncsm_duration)}" }
227
+ ncsm_sched_maint = Flapjack::Data::ScheduledMaintenance.new(:start_time => timestamp,
228
+ :end_time => timestamp + @ncsm_duration,
229
+ :summary => 'Automatically created for new check')
230
+ ncsm_sched_maint.save!
231
+ end
176
232
 
177
- event.counter = @redis.hincrby('event_counters', 'all', 1)
178
- @redis.hincrby("event_counters:#{@instance_id}", 'all', 1)
233
+ check.save! # no-op if not new and not changed
234
+ check.scheduled_maintenances << ncsm_sched_maint unless ncsm_sched_maint.nil?
179
235
 
180
- # FIXME skip if entity_check.nil?
236
+ @global_stats.save!
237
+ @instance_stats.save!
181
238
 
182
- # FIXME: validate that the event is sane before we ever get here
183
- # FIXME: create an event if there is dodgy data
239
+ if (old_state.nil? || old_state.condition.nil?) && !event_condition.nil? &&
240
+ Flapjack::Data::Condition.healthy?(event_condition.name)
184
241
 
185
- case event.type
186
- # Service events represent current state of checks on monitored systems
187
- when 'service'
188
- if event.failure?
189
- # ensure that the check's hash is stored for later lookup
190
- # can't happen inside the multi as it must get a value
191
- event.id_hash = entity_check.ack_hash
192
- end
242
+ new_state.save!
243
+ check.states << new_state
244
+ check.current_state = new_state
245
+ old_state.destroy unless old_state.nil? # will fail if still linked
246
+
247
+ # If the service event's condition is ok and there was no previous condition, don't alert.
248
+ # This stops new checks from alerting as "recovery" after they have been added.
249
+ Flapjack.logger.debug {
250
+ "Not generating notification for event #{event.id} because " \
251
+ "filtering was skipped"
252
+ }
253
+
254
+ else
255
+ # only change notification delays on service (non-action) events;
256
+ # fall back to check-local, config-global or default values unless
257
+ # sustained by the event flow
258
+ init_fail_delay = (event_condition.nil? ? nil : event.initial_failure_delay) ||
259
+ check.initial_failure_delay ||
260
+ @initial_failure_delay ||
261
+ Flapjack::DEFAULT_INITIAL_FAILURE_DELAY
262
+
263
+ repeat_fail_delay = (event_condition.nil? ? nil : event.repeat_failure_delay) ||
264
+ check.repeat_failure_delay ||
265
+ @repeat_failure_delay ||
266
+ Flapjack::DEFAULT_REPEAT_FAILURE_DELAY
267
+
268
+ filter_opts = {
269
+ :initial_failure_delay => init_fail_delay,
270
+ :repeat_failure_delay => repeat_fail_delay,
271
+ :old_state => old_state, :new_state => new_state,
272
+ :timestamp => timestamp, :duration => event.duration
273
+ }
274
+
275
+ # acks only go into latest_notifications
276
+ save_to_history = new_state.action.nil? && !event_condition.nil? &&
277
+ (old_state.nil? || (old_state.condition != event_condition.name))
278
+
279
+ if save_to_history
280
+ new_state.save!
281
+ check.states << new_state
282
+ check.current_state = new_state
283
+ elsif new_state.action.nil?
284
+ old_state.updated_at = timestamp
285
+ old_state.summary = new_state.summary
286
+ old_state.details = new_state.details
287
+ old_state.save!
288
+ end
289
+
290
+ blocker = @filters.find {|f| f.block?(check, filter_opts) }
193
291
 
194
- @redis.multi do |multi|
195
- if event.ok?
196
- multi.hincrby('event_counters', 'ok', 1)
197
- multi.hincrby("event_counters:#{@instance_id}", 'ok', 1)
198
- elsif event.failure?
199
- multi.hincrby('event_counters', 'failure', 1)
200
- multi.hincrby("event_counters:#{@instance_id}", 'failure', 1)
292
+ if blocker.nil?
293
+ Flapjack.logger.info { "Generating notification for event #{event.dump}" }
294
+ new_state.save! unless new_state.persisted?
295
+ generate_notification(check, old_state, new_state, event,
296
+ event_condition)
201
297
  else
202
- multi.hincrby('event_counters', 'invalid', 1)
203
- multi.hincrby("event_counters:#{@instance_id}", 'invalid', 1)
204
- @logger.error("Invalid event received: #{event.inspect}")
298
+ Flapjack.logger.debug {
299
+ "Not generating notification for event #{event.id} " \
300
+ "because this filter blocked: #{blocker.name}"
301
+ }
205
302
  end
303
+
206
304
  end
305
+ end
306
+ end
207
307
 
208
- previous_state = entity_check.state
308
+ def update_check(check, old_state, new_state, event, event_condition, timestamp)
309
+ @global_stats.all_events += 1
310
+ @instance_stats.all_events += 1
209
311
 
210
- if previous_state.nil?
211
- @logger.info("No previous state for event #{event.id}")
312
+ event.counter = @global_stats.all_events
212
313
 
213
- if @ncsm_duration > 0 && (event.tags & @ncsm_ignore_tags).empty?
214
- @logger.info("Setting scheduled maintenance for #{time_period_in_words(@ncsm_duration)}")
215
- entity_check.create_scheduled_maintenance(timestamp,
216
- @ncsm_duration, :summary => 'Automatically created for new check')
217
- end
314
+ # ncsm_sched_maint = nil
218
315
 
219
- # If the service event's state is ok and there was no previous state, don't alert.
220
- # This stops new checks from alerting as "recovery" after they have been added.
221
- if event.ok?
222
- @logger.debug("setting skip_filters to true because there was no previous state and event is ok")
223
- result = false
224
- end
225
- end
316
+ if event_condition.nil?
317
+ # Action events represent human or automated interaction with Flapjack
318
+ new_state.action = event.state
319
+ new_state.condition = old_state.condition unless old_state.nil?
226
320
 
227
- entity_check.update_state(event.state, :timestamp => timestamp,
228
- :summary => event.summary, :count => event.counter,
229
- :details => event.details, :perfdata => event.perfdata,
230
- :initial_failure_delay => event.initial_failure_delay,
231
- :repeat_failure_delay => event.repeat_failure_delay)
232
-
233
- entity_check.update_current_scheduled_maintenance
234
-
235
- # Action events represent human or automated interaction with Flapjack
236
- when 'action'
237
- # When an action event is processed, store the event.
238
- @redis.multi do |multi|
239
- multi.hset(event.id + ':actions', timestamp, event.state)
240
- multi.hincrby('event_counters', 'action', 1)
241
- multi.hincrby("event_counters:#{@instance_id}", 'action', 1)
321
+ unless new_state.action =~ /\Atest_notifications(?:\s+#{Flapjack::Data::Condition.unhealthy.keys.join('|')})?\z/
322
+ @global_stats.action_events += 1
323
+ @instance_stats.action_events += 1
242
324
  end
243
325
  else
244
- @redis.multi do |multi|
245
- multi.hincrby('event_counters', 'invalid', 1)
246
- multi.hincrby("event_counters:#{@instance_id}", 'invalid', 1)
326
+ # Service events represent current state of checks on monitored systems
327
+ check.failing = !Flapjack::Data::Condition.healthy?(event_condition.name)
328
+ check.condition = event_condition.name
329
+
330
+ if check.failing
331
+ @global_stats.failure_events += 1
332
+ @instance_stats.failure_events += 1
333
+ else
334
+ @global_stats.ok_events += 1
335
+ @instance_stats.ok_events += 1
247
336
  end
248
- @logger.error("Invalid event received: #{event.inspect}")
337
+
338
+ new_state.condition = event_condition.name
339
+ new_state.perfdata = event.perfdata
249
340
  end
250
341
 
251
- [result, previous_state]
342
+ new_state.summary = event.summary
343
+ new_state.details = event.details
252
344
  end
253
345
 
254
- def generate_notification(event, entity_check, timestamp, previous_state)
255
- notification_type = Flapjack::Data::Notification.type_for_event(event)
256
- max_notified_severity = entity_check.max_notified_severity_of_current_failure
346
+ def generate_notification(check, old_state, new_state, event, event_condition)
347
+ severity = nil
348
+
349
+ # accepts test_notifications without condition, for backwards compatibility
350
+ if new_state.action =~ /\Atest_notifications(\s+#{Flapjack::Data::Condition.unhealthy.keys.join('|')})?\z/
351
+ # the state won't be preserved for any time after the notification is
352
+ # sent via association to a state or check
353
+ severity = Regexp.last_match(1) || Flapjack::Data::Condition.most_unhealthy
354
+ else
355
+ latest_notif = check.latest_notifications
257
356
 
258
- @redis.multi do |multi|
259
- multi.set("#{event.id}:last_#{notification_type}_notification", timestamp)
260
- multi.set("#{event.id}:last_#{event.state}_notification", timestamp) if event.failure?
261
- multi.rpush("#{event.id}:#{notification_type}_notifications", timestamp)
262
- multi.rpush("#{event.id}:#{event.state}_notifications", timestamp) if event.failure?
357
+ notification_ids_to_remove = if new_state.action.nil?
358
+ latest_notif.intersect(:condition => new_state.condition).ids
359
+ else
360
+ latest_notif.intersect(:action => new_state.action).ids
361
+ end
362
+ latest_notif.add(new_state)
363
+ latest_notif.remove_ids(*notification_ids_to_remove) unless notification_ids_to_remove.empty?
364
+
365
+ most_severe = check.most_severe
366
+
367
+ most_severe_cond = most_severe.nil? ? nil :
368
+ Flapjack::Data::Condition.for_name(most_severe.condition)
369
+
370
+ if !event_condition.nil? &&
371
+ Flapjack::Data::Condition.unhealthy.has_key?(event_condition.name) &&
372
+ (most_severe_cond.nil? || (event_condition < most_severe_cond))
373
+
374
+ check.most_severe = new_state
375
+ most_severe_cond = event_condition
376
+ elsif 'acknowledgement'.eql?(new_state.action)
377
+ check.most_severe = nil
378
+ end
379
+
380
+ severity = most_severe_cond.nil? ? 'ok' : most_severe_cond.name
263
381
  end
264
382
 
265
- @logger.debug("Notification of type #{notification_type} is being generated for #{event.id}: " + event.inspect)
383
+ Flapjack.logger.info { "severity #{severity}"}
266
384
 
267
- severity = Flapjack::Data::Notification.severity_for_event(event, max_notified_severity)
385
+ Flapjack.logger.debug("Notification is being generated for #{event.id}: " + event.inspect)
268
386
 
269
- lc = entity_check.last_change
270
- state_duration = lc ? (timestamp - lc) : nil
387
+ event_hash = (event_condition.nil? || Flapjack::Data::Condition.healthy?(event_condition.name)) ?
388
+ nil : check.ack_hash
271
389
 
272
- Flapjack::Data::Notification.add(@notifier_queue, event,
273
- :type => notification_type, :severity => severity,
274
- :last_state => previous_unique_state(entity_check), :state_duration => state_duration,
275
- :redis => @redis)
276
- end
390
+ condition_duration = old_state.nil? ? nil :
391
+ (new_state.created_at - old_state.created_at)
277
392
 
278
- def previous_unique_state(entity_check)
279
- hs = entity_check.historical_states(nil, nil, :order => 'desc', :limit => 2)
280
- return { :last_state => nil, :last_summary => nil } unless hs.length == 2
281
- return hs.last
282
- end
393
+ notification = Flapjack::Data::Notification.new(:duration => event.duration,
394
+ :severity => severity, :condition_duration => condition_duration,
395
+ :event_hash => event_hash)
396
+ notification.save!
397
+
398
+ notification.state = new_state
399
+ check.notifications << notification
400
+
401
+ @notifier_queue.push(notification)
402
+
403
+ return if new_state.action =~ /\Atest_notifications(?:\s+#{Flapjack::Data::Condition.unhealthy.keys.join('|')})?\z/
404
+
405
+ Flapjack.logger.info "notification count: #{check.notification_count}"
283
406
 
407
+ if check.notification_count.nil?
408
+ check.notification_count = 1
409
+ else
410
+ check.notification_count += 1
411
+ end
412
+ check.save!
413
+
414
+ Flapjack.logger.info "#{check.name} #{check.errors.full_messages} notification count: #{check.notification_count}"
415
+ end
284
416
  end
285
417
  end