flapjack 1.6.0 → 2.0.0b1

Sign up to get free protection for your applications and to get access to all the features.
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