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
@@ -38,41 +38,41 @@
38
38
  <table class="table table-bordered table-hover table-condensed">
39
39
  <tr>
40
40
  <td>Events queued:</td>
41
- <td><%= h @events_queued %></td>
42
- </tr>
43
- <tr>
44
- <td>Number of enabled entities:</td>
45
- <td><%= h @count_current_entities %></td>
46
- </tr>
47
- <tr>
48
- <td>Number of failing entities:</td>
49
- <td><%= h @count_failing_entities %></td>
41
+ <td><%= h @metrics[:event_queue_length] %></td>
50
42
  </tr>
51
43
  <tr>
52
44
  <td>Number of enabled checks:</td>
53
- <td><%= h @count_current_checks %></td>
45
+ <td><%= h @metrics[:check_counts][:enabled] %></td>
54
46
  </tr>
55
47
  <tr>
56
48
  <td>Number of failing checks:</td>
57
- <td><%= h @count_failing_checks %></td>
49
+ <td><%= h @metrics[:check_counts][:failing] %></td>
58
50
  </tr>
59
51
  <tr>
60
- <td>Events processed (all time)</td>
61
- <td>
62
- <ul>
63
- <li>all: <%= h @event_counters['all'] %> events</li>
64
- <li>ok: <%= h @event_counters['ok'] %> events</li>
65
- <li>failure: <%= h @event_counters['failure'] %> events</li>
66
- <li>action: <%= h @event_counters['action'] %> events</li>
67
- <li>invalid: <%= h @event_counters['invalid'] %> events</li>
68
- </ul>
69
- </td>
52
+ <td>Number of disabled checks:</td>
53
+ <td><%= h @metrics[:check_counts][:all] - @metrics[:check_counts][:enabled] %></td>
54
+ </tr>
55
+ <tr>
56
+ <% if @global_stats.nil? %>
57
+ <td colspan="2">No statistics found.</td>
58
+ <% else %>
59
+ <td>Events processed (all time)</td>
60
+ <td>
61
+ <ul>
62
+ <li>all: <%= h @global_stats[:all_events] %> events</li>
63
+ <li>ok: <%= h @global_stats[:ok_events] %> events</li>
64
+ <li>failure: <%= h @global_stats[:failure_events] %> events</li>
65
+ <li>action: <%= h @global_stats[:action_events] %> events</li>
66
+ <li>invalid: <%= h @global_stats[:invalid_events] %> events</li>
67
+ </ul>
68
+ </td>
69
+ <% end %>
70
70
  </tr>
71
71
  <tr>
72
72
  <td>Check Freshness</td>
73
73
  <td>
74
74
  <ul>
75
- <% @current_checks_ages.each_pair do |age, check_count| %>
75
+ <% @metrics[:check_freshness].each_pair do |age, check_count| %>
76
76
  <li>&gt;= <%= h age %>: <%= h check_count %></li>
77
77
  <% end %>
78
78
  </ul>
@@ -80,7 +80,7 @@
80
80
  </tr>
81
81
  <tr>
82
82
  <td>Total keys in redis</td>
83
- <td><%= h @dbsize %></td>
83
+ <td><%= h @metrics[:total_keys] %></td>
84
84
  </tr>
85
85
  <tr>
86
86
  <td>Current time</td>
@@ -97,13 +97,12 @@
97
97
  <th>Uptime</th>
98
98
  <th>Events Processed</th>
99
99
  </tr>
100
- <% @executive_instances.sort_by {|i, d| d['uptime']}.each do |ei| %>
100
+ <% @executive_instances.sort_by {|i, d| d[:uptime]}.each do |ei| %>
101
101
  <%
102
102
  instance_id, details = ei
103
103
  hostname, pid = instance_id.split(':')
104
- started = details['uptime_string']
105
- event_counters = details['event_counters']
106
- event_rates = details['event_rates']
104
+ started = details[:uptime_string]
105
+ event_rates = details[:event_rates]
107
106
  %>
108
107
  <tr>
109
108
  <td><%= h hostname %></td>
@@ -111,11 +110,11 @@
111
110
  <td><%= h started %></td>
112
111
  <td>
113
112
  <ul>
114
- <li>all: <%= h event_counters['all'] %> (<%= h event_rates['all'] %> events/s)</li>
115
- <li>ok: <%= h event_counters['ok'] %> (<%= h event_rates['ok'] %> events/s)</li>
116
- <li>failure: <%= h event_counters['failure'] %> (<%= h event_rates['failure'] %> events/s)</li>
117
- <li>action: <%= h event_counters['action'] %> (<%= h event_rates['action'] %> events/s)</li>
118
- <li>invalid: <%= h event_counters['invalid'] %> (<%= h event_rates['invalid'] %> events/s)</li>
113
+ <li>all: <%= h details[:all_events] %> (<%= h event_rates[:all_events] %> events/s)</li>
114
+ <li>ok: <%= h details[:ok_events] %> (<%= h event_rates[:ok_events] %> events/s)</li>
115
+ <li>failure: <%= h details[:failure_events] %> (<%= h event_rates[:failure_events] %> events/s)</li>
116
+ <li>action: <%= h details[:action_events] %> (<%= h event_rates[:action_events] %> events/s)</li>
117
+ <li>invalid: <%= h details[:invalid_events] %> (<%= h event_rates[:invalid_events] %> events/s)</li>
119
118
  </ul>
120
119
  </td>
121
120
  </tr>
@@ -125,7 +124,7 @@
125
124
  </div>
126
125
 
127
126
  <p>
128
- <a class="btn btn-success" href="<% @base_url %>self_stats.json">View as JSON</a>
127
+ <a class="btn btn-success" href="<%= @base_url %>self_stats.json">View as JSON</a>
129
128
  Learn how to
130
129
  <a href="http://flapjack.io/docs/1.0/development/Gathering-internal-statistics-with-collectd"> use these metrics</a>.
131
130
  </p>
@@ -0,0 +1,32 @@
1
+ <% page_title "Tag: #{h @tag[:name]}" %>
2
+
3
+ <div class="page-header">
4
+ <h2>Tag: <%= h @tag[:name] %></h2>
5
+ </div>
6
+
7
+ <% if @checks.nil? || @checks.empty? %>
8
+ <p>No checks</p>
9
+ <% else %>
10
+ <table class="table table-bordered table-hover table-condensed">
11
+ <tr>
12
+ <th>Name</th>
13
+ <th>Failing?</th>
14
+ </tr>
15
+ <% @checks.each do |check| %>
16
+ <tr>
17
+ <td><a href="<%= @base_url %>checks/<%= check[:id] %>" title="check details"><%= h check[:name] %></a></td>
18
+ <td><%=
19
+ case check[:failing]
20
+ when true
21
+ 'Y'
22
+ when false
23
+ 'N'
24
+ else
25
+ '?'
26
+ end %></a></td>
27
+ </tr>
28
+ <% end %>
29
+ </table>
30
+ <% end %>
31
+ <br>
32
+
@@ -0,0 +1,51 @@
1
+ <% page_title 'Tags' %>
2
+
3
+ <div class="page-header">
4
+ <h2>Tags</h2>
5
+ </div>
6
+
7
+ <div class="row">
8
+ <div class="col-md-8">
9
+
10
+ <form action="<%= @base_url %>tags" method="get" role="form" class="form-horizontal">
11
+
12
+ <div class="form-group">
13
+ <label class="col-sm-2 control-label" for="start_time">Name:</label>
14
+ <div class="col-sm-10">
15
+ <input type="text" name="name" class="form-control" size="20" maxlength="80" value="<%= h params[:name] %>">
16
+ <span class="help-block">
17
+ e.g. the exact name, or a /regexp/
18
+ </span>
19
+ </div>
20
+
21
+ <div class="form-group">
22
+ <div class="col-sm-2"></div>
23
+ <div class="col-sm-10">
24
+ <button type="submit" class="btn btn-success">Refresh</button>
25
+ </div>
26
+ </div>
27
+
28
+ </div>
29
+
30
+ </form><!-- form-horizontal-->
31
+
32
+ </div>
33
+ </div>
34
+
35
+ <% if !@tags || @tags.empty? %>
36
+ <p>No tags</p>
37
+ <% else %>
38
+ <table class="table table-bordered table-hover table-condensed">
39
+ <tr>
40
+ <th>Name</th>
41
+ </tr>
42
+ <% @tags.each do |tag| %>
43
+ <tr>
44
+ <td><a href="<%= @base_url %>tags/<%= tag[:id] %>" title="tag details"><%= h tag[:name] %></a></td>
45
+ </tr>
46
+ <% end %>
47
+ </table>
48
+ <% end %>
49
+ <br>
50
+
51
+ <%= erb '_pagination.html'.to_sym, :layout => false %>
@@ -6,6 +6,26 @@ require 'monitor'
6
6
 
7
7
  module Flapjack
8
8
 
9
+ class << self
10
+ # Thread and fiber-local
11
+
12
+ def configure_log(name, config = {})
13
+ Thread.current[:flapjack_logger_name] = name
14
+ Thread.current[:flapjack_logger_config] = config
15
+ end
16
+
17
+ def logger=(l)
18
+ Thread.current[:flapjack_logger] = l
19
+ end
20
+
21
+ def logger
22
+ Thread.current[:flapjack_logger] ||= Flapjack::Logger.new(
23
+ Thread.current[:flapjack_logger_name] || 'default',
24
+ Thread.current[:flapjack_logger_config] || {}
25
+ )
26
+ end
27
+ end
28
+
9
29
  class Logger
10
30
 
11
31
  LEVELS = [:debug, :info, :warn, :error, :fatal]
@@ -26,10 +46,20 @@ module Flapjack
26
46
 
27
47
  @formatter = proc do |severity, datetime, progname, msg|
28
48
  t = datetime.iso8601(6)
29
- "#{t} [#{severity}] :: #{name} :: #{msg}\n"
49
+ "#{t} [#{severity}] :: #{@name} :: #{msg}\n"
50
+ end
51
+
52
+ output = if config[:file].nil? || config[:file].empty? ||
53
+ !File.exists?(File.dirname(config[:file])) ||
54
+ !File.writable?(File.dirname(config[:file])) ||
55
+ (File.exists?(config[:file]) && !File.writable?(config[:file]))
56
+
57
+ STDOUT
58
+ else
59
+ config[:file]
30
60
  end
31
61
 
32
- @logger = ::Logger.new(STDOUT)
62
+ @logger = ::Logger.new(output)
33
63
  @logger.formatter = @formatter
34
64
 
35
65
  configure(config)
@@ -103,7 +133,7 @@ module Flapjack
103
133
  end
104
134
 
105
135
  LEVELS.each do |level|
106
- define_method(level) {|progname, &block|
136
+ define_method(level) {|progname = nil, &block|
107
137
  add(::Logger.const_get(level.upcase), nil, progname, &block)
108
138
  }
109
139
  end
@@ -112,6 +142,7 @@ module Flapjack
112
142
  (LEVELS + [:configure, :close, :add]).include?(sym)
113
143
  end
114
144
 
145
+
115
146
  ['debug', 'info', 'warn', 'error', 'fatal'].each { |level|
116
147
  define_method("#{level}?") {
117
148
  @logger.send("#{level}?")
@@ -2,23 +2,16 @@
2
2
 
3
3
  require 'active_support/time'
4
4
 
5
- require 'em-hiredis'
5
+ require 'flapjack/exceptions'
6
+ require 'flapjack/redis_proxy'
7
+ require 'flapjack/record_queue'
8
+ require 'flapjack/utility'
6
9
 
7
10
  require 'flapjack/data/alert'
8
-
11
+ require 'flapjack/data/check'
9
12
  require 'flapjack/data/contact'
10
- require 'flapjack/data/entity_check'
11
- require 'flapjack/data/notification'
12
13
  require 'flapjack/data/event'
13
- require 'flapjack/redis_pool'
14
- require 'flapjack/utility'
15
-
16
- require 'flapjack/gateways/email'
17
- require 'flapjack/gateways/sms_messagenet'
18
- require 'flapjack/gateways/slack'
19
- require 'flapjack/gateways/sms_twilio'
20
- require 'flapjack/gateways/sms_nexmo'
21
- require 'flapjack/gateways/aws_sns'
14
+ require 'flapjack/data/notification'
22
15
 
23
16
  module Flapjack
24
17
 
@@ -27,61 +20,45 @@ module Flapjack
27
20
  include Flapjack::Utility
28
21
 
29
22
  def initialize(opts = {})
30
- @config = opts[:config]
31
- @redis_config = opts[:redis_config] || {}
32
- @logger = opts[:logger]
33
- @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2, :logger => @logger)
23
+ @lock = opts[:lock]
24
+ @config = opts[:config] || {}
34
25
 
35
- @notifications_queue = @config['queue'] || 'notifications'
26
+ @queue = Flapjack::RecordQueue.new(@config['queue'] || 'notifications',
27
+ Flapjack::Data::Notification)
36
28
 
37
29
  queue_configs = @config.find_all {|k, v| k =~ /_queue$/ }
38
- @queues = Hash[queue_configs.map {|k, v| [k[/^(.*)_queue$/, 1], v] }]
30
+ @queues = Hash[queue_configs.map {|k, v|
31
+ [k[/^(.*)_queue$/, 1], Flapjack::RecordQueue.new(v, Flapjack::Data::Alert)]
32
+ }]
39
33
 
40
- notify_logfile = @config['notification_log_file'] || 'log/notify.log'
41
- if not File.directory?(File.dirname(notify_logfile))
42
- puts "Parent directory for log file '#{notify_logfile}' doesn't exist"
43
- puts "Exiting!"
44
- exit
45
- end
46
- @notifylog = ::Logger.new(notify_logfile)
47
- @notifylog.formatter = proc do |severity, datetime, progname, msg|
48
- "#{datetime.to_s} | #{msg}\n"
49
- end
34
+ raise "No queues for media transports" if @queues.empty?
50
35
 
51
- tz = nil
52
36
  tz_string = @config['default_contact_timezone'] || ENV['TZ'] || 'UTC'
53
- begin
54
- tz = ActiveSupport::TimeZone.new(tz_string)
55
- rescue ArgumentError
56
- logger.error("Invalid timezone string specified in default_contact_timezone or TZ (#{tz_string})")
57
- exit_now!
37
+ tz = ActiveSupport::TimeZone[tz_string.untaint]
38
+ if tz.nil?
39
+ raise "Invalid timezone string specified in default_contact_timezone or TZ (#{tz_string})"
58
40
  end
59
41
  @default_contact_timezone = tz
60
42
  end
61
43
 
62
44
  def start
63
- @logger.info("Booting main loop.")
64
-
65
- until @should_quit
66
- @logger.debug("Waiting for notification...")
67
- notification = Flapjack::Data::Notification.next(@notifications_queue,
68
- :redis => @redis,
69
- :logger => @logger)
70
- process_notification(notification) unless notification.nil?
71
- end
45
+ begin
46
+ Zermelo.redis = Flapjack.redis
72
47
 
73
- @logger.info("Exiting main loop.")
74
- end
48
+ loop do
49
+ @lock.synchronize do
50
+ @queue.foreach {|notif| process_notification(notif) }
51
+ end
75
52
 
76
- # this must use a separate connection to the main Executive one, as it's running
77
- # from a different fiber while the main one is blocking.
78
- def stop
79
- @should_quit = true
53
+ @queue.wait
54
+ end
55
+ ensure
56
+ Flapjack.redis.quit
57
+ end
58
+ end
80
59
 
81
- redis_uri = @redis_config[:path] ||
82
- "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}"
83
- shutdown_redis = EM::Hiredis.connect(redis_uri)
84
- shutdown_redis.rpush(@notifications_queue, Flapjack.dump_json('type' => 'shutdown'))
60
+ def stop_type
61
+ :exception
85
62
  end
86
63
 
87
64
  private
@@ -90,76 +67,167 @@ module Flapjack
90
67
  # notification, updates the notification history in redis, generates the
91
68
  # notifications
92
69
  def process_notification(notification)
93
- @logger.debug ("Processing notification: #{notification.inspect}")
94
-
95
- timestamp = Time.now
96
- event_id = notification.event_id
97
- entity_check = Flapjack::Data::EntityCheck.for_event_id(event_id,
98
- :redis => @redis, :logger => @logger)
99
- contacts = entity_check.contacts
100
-
101
- if contacts.empty?
102
- @logger.debug("No contacts for #{event_id}")
103
- @notifylog.info("#{event_id} | #{notification.type} | NO CONTACTS")
104
- return
70
+ Flapjack.logger.debug { "Processing notification: #{notification.inspect}" }
71
+
72
+ check = notification.check
73
+ check_name = check.name
74
+
75
+ # TODO check whether time should come from something stored in the notification
76
+ alerts = alerts_for(notification, check, :time => Time.now)
77
+
78
+ if alerts.nil? || alerts.empty?
79
+ Flapjack.logger.info { "No alerts" }
80
+ else
81
+ Flapjack.logger.info { "Alerts: #{alerts.size}" }
82
+
83
+ alerts.each do |alert|
84
+ medium = alert.medium
85
+
86
+ Flapjack.logger.info {
87
+ "#{check_name} | #{medium.contact.id} | " \
88
+ "#{medium.transport} | #{medium.address}\n" \
89
+ "Enqueueing #{medium.transport} alert for " \
90
+ "#{check_name} to #{medium.address} " \
91
+ " rollup: #{alert.rollup || '-'}"
92
+ }
93
+
94
+ @queues[medium.transport].push(alert)
95
+ end
105
96
  end
106
97
 
107
- messages = notification.messages(contacts,
108
- :default_timezone => @default_contact_timezone, :logger => @logger)
109
-
110
- notification_contents = notification.contents
111
-
112
- messages.each do |message|
113
- media_type = message.medium
114
- address = message.address
115
- contents = message.contents.merge(notification_contents)
116
-
117
- if message.rollup
118
- rollup_alerts = message.contact.alerting_checks_for_media(media_type).inject({}) do |memo, alert|
119
- ec = Flapjack::Data::EntityCheck.for_event_id(alert, :redis => @redis)
120
- last_change = ec.last_change
121
- memo[alert] = {
122
- 'duration' => last_change ? (Time.now.to_i - last_change) : nil,
123
- 'state' => ec.state,
124
- 'summary' => ec.summary
125
- }
126
- memo
127
- end
128
- contents['rollup_alerts'] = rollup_alerts
129
- contents['rollup_threshold'] = message.contact.rollup_threshold_for_media(media_type)
98
+ notification.destroy
99
+ end
100
+
101
+ def alerts_for(notification, check, opts = {})
102
+ time = opts[:time]
103
+
104
+ Flapjack::Data::Medium.lock(Flapjack::Data::Check,
105
+ Flapjack::Data::ScheduledMaintenance,
106
+ Flapjack::Data::UnscheduledMaintenance,
107
+ Flapjack::Data::Rule,
108
+ Flapjack::Data::Alert,
109
+ Flapjack::Data::Tag,
110
+ Flapjack::Data::Notification,
111
+ Flapjack::Data::Contact,
112
+ Flapjack::Data::State) do
113
+
114
+ notification_state = notification.state
115
+
116
+ this_notification_ack = 'acknowledgement'.eql?(notification_state.action)
117
+ this_notification_ok = this_notification_ack ||
118
+ Flapjack::Data::Condition.healthy?(notification_state.condition)
119
+
120
+ # checks in sched/unsched maint will not be notified -- time should be taken
121
+ # from the processor's created notification, maint period check done there only
122
+ is_a_test = !(notification_state.action =~ /\Atest_notifications/).nil?
123
+
124
+ alerting_severity = is_a_test ? 'critical' : notification.severity
125
+
126
+ # clear alertable if OK, to get accurate rollup counts
127
+ if !is_a_test && !this_notification_ok
128
+ check.alertable = true
129
+ check.save
130
130
  end
131
131
 
132
- @notifylog.info("#{event_id} | " +
133
- "#{notification.type} | #{message.contact.id} | #{media_type} | #{address}")
132
+ media = check.alerting_media(:time => time, :severity => alerting_severity).all
133
+
134
+ Flapjack.logger.debug {
135
+ "Alerting media for check #{check.name}:\n" +
136
+ media.collect {|m| "#{m.transport} #{m.address}"}.join("\n")
137
+ }
134
138
 
135
- if @queues[media_type.to_s].nil?
136
- @logger.error("no queue for media type: #{media_type}")
137
- return
139
+ # clear alertable if OK, to get accurate rollup counts
140
+ if !is_a_test && this_notification_ok
141
+ check.alertable = false
142
+ check.save
138
143
  end
139
144
 
140
- @logger.info("Enqueueing #{media_type} alert for #{event_id} to #{address} type: #{notification.type} rollup: #{message.rollup || '-'}")
145
+ media.inject([]) do |memo, alerting_medium|
146
+ alert_rollup = nil
147
+ alerting_check_ids = []
148
+
149
+ unless is_a_test
150
+ rollup_count_needed = !(alerting_medium.rollup_threshold.nil? ||
151
+ (alerting_medium.rollup_threshold <= 0))
152
+
153
+ if rollup_count_needed
154
+ alerting_check_ids = alerting_medium.alerting_checks(:time => time).ids
155
+
156
+ Flapjack.logger.debug {
157
+ "Alerting checks for medium #{alerting_medium.id}:\n" +
158
+ Flapjack::Data::Check.intersect(:id => alerting_check_ids).map(&:name).join("\n")
159
+ }
160
+
161
+ end
162
+
163
+ alert_rollup = if rollup_count_needed &&
164
+ (alerting_check_ids.size >= alerting_medium.rollup_threshold)
165
+
166
+ 'problem'
167
+ else
168
+ 'problem'.eql?(alerting_medium.last_rollup_type) ? 'recovery' : nil
169
+ end
141
170
 
142
- contact = message.contact
171
+ last_state = alerting_medium.last_state
143
172
 
144
- if notification.ok? || (notification.state == 'acknowledgement')
145
- ['warning', 'critical', 'unknown'].each do |alert_state|
146
- contact.update_sent_alert_keys(
147
- :media => media_type,
148
- :check => event_id,
149
- :state => alert_state,
150
- :delete => true)
173
+ Flapjack.logger.debug "last_state #{last_state.inspect}"
174
+
175
+ last_state_ok = last_state.nil? ? nil :
176
+ (Flapjack::Data::Condition.healthy?(last_state.condition) ||
177
+ 'acknowledgement'.eql?(last_state.action))
178
+
179
+ interval_allows = last_state.nil? ||
180
+ ((last_state.created_at + (alerting_medium.interval || 0)) < notification_state.created_at)
181
+
182
+ Flapjack.logger.debug " last_state_ok = #{last_state_ok}\n" \
183
+ " interval_allows = #{interval_allows}\n" \
184
+ " alert_rollup , last_rollup_type = #{alert_rollup} , #{alerting_medium.last_rollup_type}\n" \
185
+ " condition , last_notification_condition = #{notification_state.condition} , #{last_state.nil? ? '-' : last_state.condition}\n" \
186
+ " no_previous_notification = #{last_state.nil?}\n"
187
+
188
+ next memo unless last_state.nil? ||
189
+ (!last_state_ok && this_notification_ok) ||
190
+ (alert_rollup != alerting_medium.last_rollup_type) ||
191
+ (this_notification_ack && !last_state_ok) ||
192
+ (last_state_ok && !this_notification_ok) ||
193
+ (notification_state.condition != last_state.condition) ||
194
+ interval_allows
151
195
  end
152
- else
153
- contact.update_sent_alert_keys(
154
- :media => media_type,
155
- :check => event_id,
156
- :state => notification.state)
157
- end
158
196
 
159
- contents_tags = contents['tags']
160
- contents['tags'] = contents_tags.is_a?(Set) ? contents_tags.to_a : contents_tags
197
+ alert = Flapjack::Data::Alert.new(:condition => notification_state.condition,
198
+ :action => notification_state.action,
199
+ :last_condition => (last_state.nil? ? nil : last_state.condition),
200
+ :last_action => (last_state.nil? ? nil : last_state.action),
201
+ :condition_duration => notification.condition_duration,
202
+ :acknowledgement_duration => notification.duration,
203
+ :rollup => alert_rollup)
204
+
205
+ unless alert_rollup.nil? || alerting_check_ids.empty?
206
+ alert.rollup_states = Flapjack::Data::Check.intersect(:id => alerting_check_ids).all.each_with_object({}) do |ch, m|
207
+ cond = ch.condition
208
+ m[cond] ||= []
209
+ m[cond] << ch.name
210
+ end
211
+ end
161
212
 
162
- Flapjack::Data::Alert.add(@queues[media_type.to_s], contents, :redis => @redis)
213
+ unless alert.save
214
+ raise "Couldn't save alert: #{alert.errors.full_messages.inspect}"
215
+ end
216
+
217
+ alerting_medium.alerts << alert
218
+ check.alerts << alert
219
+
220
+ Flapjack.logger.info "alerting for #{alerting_medium.transport}, #{alerting_medium.address}"
221
+
222
+ unless is_a_test
223
+ notification_state.latest_media << alerting_medium
224
+ alerting_medium.last_rollup_type = alert.rollup
225
+ alerting_medium.save
226
+ end
227
+
228
+ memo << alert
229
+ memo
230
+ end
163
231
  end
164
232
  end
165
233