status_cat 0.0.8

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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +161 -0
  4. data/Rakefile +31 -0
  5. data/app/assets/javascripts/status-cat/application.js +15 -0
  6. data/app/assets/stylesheets/status-cat/application.css +13 -0
  7. data/app/controllers/status_cat/status_controller.rb +26 -0
  8. data/app/helpers/status_cat/status_helper.rb +105 -0
  9. data/app/mailers/status_cat/status_mailer.rb +12 -0
  10. data/app/views/status_cat/status/index.html.erb +4 -0
  11. data/app/views/status_cat/status_mailer/failure.html.erb +9 -0
  12. data/app/views/status_cat/status_mailer/failure.text.erb +1 -0
  13. data/config/locales/en.yml +7 -0
  14. data/config/routes.rb +4 -0
  15. data/lib/status_cat/checkers/action_mailer.rb +31 -0
  16. data/lib/status_cat/checkers/active_record.rb +24 -0
  17. data/lib/status_cat/checkers/base.rb +36 -0
  18. data/lib/status_cat/checkers/delayed_job.rb +28 -0
  19. data/lib/status_cat/checkers/s3.rb +17 -0
  20. data/lib/status_cat/checkers/stripe.rb +19 -0
  21. data/lib/status_cat/config.rb +33 -0
  22. data/lib/status_cat/engine.rb +5 -0
  23. data/lib/status_cat/status.rb +37 -0
  24. data/lib/status_cat/version.rb +3 -0
  25. data/lib/status_cat.rb +22 -0
  26. data/lib/tasks/status_cat.rake +14 -0
  27. data/spec/controllers/status_cat/status_controller_spec.rb +36 -0
  28. data/spec/coverage_spec.rb +22 -0
  29. data/spec/data/report.txt +10 -0
  30. data/spec/data/report.txt.tmp +10 -0
  31. data/spec/data/status_report_format.txt +1 -0
  32. data/spec/data/status_report_format.txt.tmp +1 -0
  33. data/spec/dummy/README.rdoc +261 -0
  34. data/spec/dummy/Rakefile +7 -0
  35. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  36. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  37. data/spec/dummy/app/checkers/dummy.rb +10 -0
  38. data/spec/dummy/app/controllers/application_controller.rb +10 -0
  39. data/spec/dummy/app/controllers/root_controller.rb +20 -0
  40. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  41. data/spec/dummy/app/views/layouts/admin.html.erb +14 -0
  42. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  43. data/spec/dummy/app/views/root/index.html.erb +8 -0
  44. data/spec/dummy/app/views/root/mail.html.erb +1 -0
  45. data/spec/dummy/config/application.rb +54 -0
  46. data/spec/dummy/config/boot.rb +10 -0
  47. data/spec/dummy/config/database.yml +25 -0
  48. data/spec/dummy/config/environment.rb +5 -0
  49. data/spec/dummy/config/environments/development.rb +32 -0
  50. data/spec/dummy/config/environments/production.rb +69 -0
  51. data/spec/dummy/config/environments/test.rb +33 -0
  52. data/spec/dummy/config/initializers/action_mailer.rb +16 -0
  53. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/dummy/config/initializers/inflections.rb +15 -0
  55. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  56. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  57. data/spec/dummy/config/initializers/session_store.rb +8 -0
  58. data/spec/dummy/config/initializers/status_cat.rb +17 -0
  59. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  60. data/spec/dummy/config/locales/en.yml +5 -0
  61. data/spec/dummy/config/passwords.yml +5 -0
  62. data/spec/dummy/config/passwords.yml.sample +5 -0
  63. data/spec/dummy/config/routes.rb +11 -0
  64. data/spec/dummy/config.ru +4 -0
  65. data/spec/dummy/db/development.sqlite3 +0 -0
  66. data/spec/dummy/db/production.sqlite3 +0 -0
  67. data/spec/dummy/db/schema.rb +16 -0
  68. data/spec/dummy/db/test.sqlite3 +0 -0
  69. data/spec/dummy/log/development.log +889 -0
  70. data/spec/dummy/log/test.log +2474 -0
  71. data/spec/dummy/public/404.html +26 -0
  72. data/spec/dummy/public/422.html +26 -0
  73. data/spec/dummy/public/500.html +25 -0
  74. data/spec/dummy/public/favicon.ico +0 -0
  75. data/spec/dummy/script/rails +6 -0
  76. data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  77. data/spec/dummy/tmp/cache/assets/D03/1A0/sprockets%2F9007913fce90a3c1766dc0d8282bd10b +0 -0
  78. data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  79. data/spec/dummy/tmp/cache/assets/D37/670/sprockets%2Fe230d6e60a0226de8748d1e26ee741cb +0 -0
  80. data/spec/dummy/tmp/cache/assets/D3D/4E0/sprockets%2F999ebb6862b2b7ca1b20b765f12704ed +0 -0
  81. data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  82. data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  83. data/spec/dummy/tmp/cache/assets/DCB/210/sprockets%2Fdf0a443455a9d359be2e931ba70ecdfe +0 -0
  84. data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  85. data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/0891c389c9f47b48b695b65602d93a57 +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/0edf8c53de2ee6fe74108f1ecc87e457 +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/264f02aaf3a74cd5a91b5575c69b784a +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/31c22cfbb3b5f7f9e1e9a013997ad8aa +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/400d7aa6ca317151fe36fc9f02ccfc4e +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/40da66d7323888023264d2f06b7525d4 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/4bddf542ba5114155847240380cf6e7c +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/572759e0267736e8961ff1fad85cfe47 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/6cec2a8a17b78e61daecff44044e1179 +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/952a706f512b208187110eff045a0e66 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/c7d1ab26b0b22ab011a9d30f44014f06 +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/f1ebb0ab4631911fbbdf496685d8b7a0 +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  104. data/spec/dummy/tmp/pids/server.pid +1 -0
  105. data/spec/helpers/status_cat/status_helper_spec.rb +101 -0
  106. data/spec/lib/status_cat/checkers/action_mailer_spec.rb +72 -0
  107. data/spec/lib/status_cat/checkers/active_record_spec.rb +45 -0
  108. data/spec/lib/status_cat/checkers/base_spec.rb +56 -0
  109. data/spec/lib/status_cat/checkers/delayed_job_spec.rb +15 -0
  110. data/spec/lib/status_cat/checkers/s3_spec.rb +15 -0
  111. data/spec/lib/status_cat/checkers/stripe_spec.rb +15 -0
  112. data/spec/lib/status_cat/config_spec.rb +133 -0
  113. data/spec/lib/status_cat/engine_spec.rb +9 -0
  114. data/spec/lib/status_cat/status_spec.rb +120 -0
  115. data/spec/lib/status_cat/version_spec.rb +11 -0
  116. data/spec/lib/status_cat_spec.rb +21 -0
  117. data/spec/lib/tasks/status_cat.rake_spec.rb +32 -0
  118. data/spec/mailers/status_cat/status_mailer_spec.rb +38 -0
  119. data/spec/spec_helper.rb +50 -0
  120. data/spec/support/shared/checker.rb +25 -0
  121. data/spec/views/status_cat/status/index.html.erb_spec.rb +25 -0
  122. data/spec/views/status_cat/status_mailer/failure.html.erb_spec.rb +16 -0
  123. data/spec/views/status_cat/status_mailer/failure.text.erb_spec.rb +15 -0
  124. metadata +373 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4d7e541b0764d848791a7a4b5d56e20de702db5
4
+ data.tar.gz: d072d488b05aa95fb5c2de5b6f166e81c169418d
5
+ SHA512:
6
+ metadata.gz: 8db8481cfa3edcd43bfb3b369a6ae5a63f2d0201f99d95ceca48ef129a57bbd7d96f946ab2343dde8b8da7b8ee71d918c1dc2a883a8658cf34fc88cb59ffac71
7
+ data.tar.gz: 4bc2df86a682d5c0e1ad4567c269878345f4bffb9657c5552e33ce2da9779ca3c35c8045073c4d0e1c874c24995a6377f8f3d19e8b65158bab5679053ab381b4
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 SchrodingersBox.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # schrodingersbox/status_cat README
2
+
3
+ This engine makes monitoring the status of your Rails environment easier.
4
+
5
+ It provides a Rails action with a green light / red light list of configured services,
6
+ such as:
7
+
8
+ * ActionMailer
9
+ * ActiveRecord
10
+ * AWS S3
11
+ * Delayed Job
12
+ * Stripe
13
+
14
+ ## Getting Started
15
+
16
+ 1. Add this to your `Gemfile` and `bundle install`
17
+
18
+ gem 'status_cat', :git => 'https://github.com/schrodingersbox/status_cat.git'
19
+
20
+ 2. Add this to your `config/routes.rb`
21
+
22
+ mount StatusCat::Engine => '/status_cat'
23
+
24
+ 3. Restart your Rails server
25
+
26
+ 4. Run `rake status_cat:check` for a text status report
27
+
28
+ 5. Visit http://yourapp/status_cat in a browser for an HTML status report
29
+
30
+ ## Configuration
31
+
32
+ All configuration should go in `config/initializers/status_cat.rb`.
33
+
34
+ Status.configure do |config|
35
+
36
+ config.authenticate_with do
37
+ authenticate!
38
+ end
39
+
40
+ config.authorize_with do
41
+ authorize!
42
+ end
43
+
44
+ config.layout = 'admin'
45
+
46
+ config.noreply = 'noreply@schrodingersbox.com'
47
+ config.to = 'ops@schrodingersbox.com'
48
+ config.from = 'ops@schrodingersbox.com'
49
+ config.subject = "#{Rails.env.upcase} StatusCat Failure"
50
+
51
+ end
52
+
53
+ ## How To
54
+
55
+ ### Configure Enabled Checkers
56
+
57
+ By default, all subclasses of StatusCat::Checkers::Base will be run. Do the following if you would like to limit or reorder the set of checkers
58
+
59
+ Create or add to `config/initializers/status_cat.rb`
60
+
61
+ StatusCat.configure do |config|
62
+ config.enabled = [ :action_mailer, :active_record ]
63
+ end
64
+
65
+ ### Configure Email Settings
66
+
67
+ Create or add to `config/initializers/status_cat.rb`
68
+
69
+ StatusCat.configure do |config|
70
+ config.noreply = 'noreply@schrodingersbox.com'
71
+ config.to = 'ops@schrodingersbox.com'
72
+ config.from = 'ops@schrodingersbox.com'
73
+ config.subject = "#{Rails.env.upcase} StatusCat Failure"
74
+ end
75
+
76
+ ### Run Status Checks From A Cron
77
+
78
+ 1. Run `rake status_cat:cron` from a cron job or other scheduling system.
79
+
80
+ PLEASE NOTE: The :action_mailer checker will attempt to send a test email to your `StatusCat.config.noreply` email address. This could cause unwanted spam or incur charges if you're using a metered mail transfer agent, like SendGrid.
81
+
82
+ ### Add New Checkers
83
+
84
+ You can place new checkers anywhere you like, but `app/checkers` is the recommended location.
85
+
86
+ 1. Add the following to `config/application.rb`
87
+
88
+ Dir[Rails.root + 'app/checkers/**/*.rb'].each { |path| require path }
89
+
90
+ 2. Create a new subclass of `StatusCat::Checkers::Base` that sets `@value` and `@status` instance variables.
91
+
92
+ module StatusCat
93
+ module Checkers
94
+ class Dummy < Base
95
+ def initialize
96
+ @value = 'dummy'
97
+ @status = 'fail'
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ ### Require authentication
104
+
105
+ Create or add to `config/initializers/status_cat.rb`
106
+
107
+ StatusCat.configure do |config|
108
+ config.authenticate_with do
109
+ warden.authenticate! scope: :user
110
+ end
111
+ end
112
+
113
+ ### Require authorization
114
+
115
+ Create or add to `config/initializers/status_cat.rb`
116
+
117
+ StatusCat.configure do |config|
118
+ config.authorize_with do
119
+ redirect_to main_app.root_path unless current_user.try(:admin?)
120
+ end
121
+ end
122
+
123
+ ### Apply a custom layout
124
+
125
+ Create or add to `config/initializers/status_cat.rb`
126
+
127
+ StatusCat.configure do |config|
128
+ config.layout = 'admin'
129
+ end
130
+
131
+ ## Reference
132
+
133
+ * [Getting Started with Engines](http://edgeguides.rubyonrails.org/engines.html)
134
+ * [Testing Rails Engines With Rspec](http://whilefalse.net/2012/01/25/testing-rails-engines-rspec/)
135
+ * [How do I write a Rails 3.1 engine controller test in rspec?](http://stackoverflow.com/questions/5200654/how-do-i-write-a-rails-3-1-engine-controller-test-in-rspec)
136
+ * [Best practice for specifying dependencies that cannot be put in gemspec?](https://groups.google.com/forum/?fromgroups=#!topic/ruby-bundler/U7FMRAl3nJE)
137
+ * [Clarifying the Roles of the .gemspec and Gemfile](http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/)
138
+ * [The Semi-Isolated Rails Engine](http://bibwild.wordpress.com/2012/05/10/the-semi-isolated-rails-engine/)
139
+ * [config.reload_plugins = true only works in environment.rb](https://rails.lighthouseapp.com/projects/8994/tickets/2324-configreload_plugins-true-only-works-in-environmentrb?spam=1)
140
+ * [describe vs. context in rspec](http://lmws.net/describe-vs-context-in-rspec)
141
+ * [Add Achievement Badges to Your Gem README](http://elgalu.github.io/2013/add-achievement-badges-to-your-gem-readme/)
142
+ * [Publishing your gem](http://guides.rubygems.org/publishing/)
143
+
144
+ ## History
145
+
146
+ Version 0.0.2 = Rails 3 compatible
147
+ Version 0.0.3 = Rails 4 compatible
148
+
149
+ ## TODO
150
+
151
+ * Add disk space checker with externally configurable limit
152
+ * Add Zencoder checker?
153
+ * Add NewRelic checker?
154
+
155
+ * Dynamically create rake tasks for each checker
156
+
157
+ * Doc
158
+ * General checker concept
159
+ * Shared spec
160
+
161
+ * Publish as gem
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ begin
9
+ require 'rdoc/task'
10
+ rescue LoadError
11
+ require 'rdoc/rdoc'
12
+ require 'rake/rdoctask'
13
+ RDoc::Task = Rake::RDocTask
14
+ end
15
+
16
+ RDoc::Task.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'StatusCat'
19
+ rdoc.options << '--line-numbers'
20
+ rdoc.rdoc_files.include('README.rdoc')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
25
+ load 'rails/tasks/engine.rake'
26
+
27
+
28
+
29
+ Bundler::GemHelper.install_tasks
30
+
31
+ load 'tasks/spec_cat.rake'
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,26 @@
1
+ class StatusCat::StatusController < ApplicationController
2
+
3
+ layout :set_layout
4
+
5
+ before_filter :_authenticate!
6
+ before_filter :_authorize!
7
+
8
+ def index
9
+ @checkers = StatusCat::Status.all
10
+ end
11
+
12
+ private
13
+
14
+ def set_layout
15
+ return StatusCat.config.layout
16
+ end
17
+
18
+ def _authenticate!
19
+ instance_eval( &StatusCat.config.authenticate_with )
20
+ end
21
+
22
+ def _authorize!
23
+ instance_eval( &StatusCat.config.authorize_with )
24
+ end
25
+
26
+ end
@@ -0,0 +1,105 @@
1
+ module StatusCat::StatusHelper
2
+
3
+ # Constructs an HTML table header
4
+
5
+ def status_header
6
+ content_tag( :tr ) do
7
+ concat content_tag( :th, t( :name, :scope => :status_cat ) )
8
+ concat content_tag( :th, t( :value, :scope => :status_cat ) )
9
+ concat content_tag( :th, t( :status, :scope => :status_cat ) )
10
+ end
11
+ end
12
+
13
+ # Constructs an HTML table row
14
+
15
+ def status_row( checker )
16
+ content_tag( :tr ) do
17
+ concat content_tag( :td, checker.name, :style => status_style( checker ) )
18
+ concat content_tag( :td, checker.value )
19
+ concat status_cell(checker.status || t( :ok, :scope => :status_cat ))
20
+ end
21
+ end
22
+
23
+ def status_cell( status )
24
+ if status.kind_of?(Array)
25
+ return content_tag( :td ) do
26
+ content_tag( :table ) do
27
+ rows = nil
28
+ status.each do |s|
29
+ row = content_tag( :tr ) do
30
+ content_tag( :td, s )
31
+ end
32
+
33
+ if rows == nil
34
+ rows = row
35
+ else
36
+ rows += row
37
+ end
38
+ end
39
+ rows
40
+ end
41
+ end
42
+ end
43
+
44
+ return content_tag( :td, status )
45
+ end
46
+
47
+ # Returns an HTML style for the status table cell
48
+
49
+ def status_style( checker )
50
+ "background-color: #{checker.status.nil? ? :green : :red}"
51
+ end
52
+
53
+ # Returns an HTML table
54
+
55
+ def status_table( checkers )
56
+ content_tag( :table, :border => 1 ) do
57
+ concat status_header
58
+ checkers.each { |checker| concat status_row( checker ) }
59
+ end
60
+ end
61
+
62
+ # Returns an HTML title
63
+
64
+ def status_title
65
+ content_tag( :h1, t( :h1, :scope => :status_cat ) )
66
+ end
67
+
68
+ # Constructs a text status report
69
+
70
+ def status_report( checkers )
71
+ format, format_length = status_report_format( checkers )
72
+ header = status_report_header( format )
73
+ length = [ format_length, header.length ].max
74
+ separator = ( '-' * length ) + "\n"
75
+
76
+ result = separator + header + separator
77
+ checkers.each { |checker| result << checker.to_s( format ) }
78
+ result << separator
79
+
80
+ return result
81
+ end
82
+
83
+ # Generate a format string to justify all values
84
+
85
+ def status_report_format( checkers )
86
+ name_max = checkers.map { |c| c.name.to_s.length }.max
87
+ value_max = checkers.map { |c| c.value.to_s.length }.max
88
+ status_max = checkers.map { |c| c.status.to_s.length }.max
89
+
90
+ format = "%#{name_max}s | %#{value_max}s | %#{status_max}s\n"
91
+ length = name_max + 3 + value_max + 3 + status_max
92
+
93
+ return format, length
94
+ end
95
+
96
+ # Generate a header string
97
+
98
+ def status_report_header( format = StatusCat::Checkers::Base::FORMAT )
99
+ name = I18n.t( :name, :scope => :status_cat )
100
+ value = I18n.t( :value, :scope => :status_cat )
101
+ status = I18n.t( :status, :scope => :status_cat )
102
+ return sprintf( format, name, value, status )
103
+ end
104
+
105
+ end
@@ -0,0 +1,12 @@
1
+ class StatusCat::StatusMailer < ActionMailer::Base
2
+
3
+ add_template_helper( StatusCat::StatusHelper )
4
+
5
+ def failure( checkers )
6
+ @checkers = checkers
7
+
8
+ config = StatusCat.config
9
+ mail( :to => config.to, :from => config.from, :subject => config.subject )
10
+ end
11
+
12
+ end
@@ -0,0 +1,4 @@
1
+ <div class="status_cat">
2
+ <%= status_title %>
3
+ <%= status_table( @checkers ) %>
4
+ </div>
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
5
+ </head>
6
+ <body>
7
+ <%= status_table( @checkers ) %>
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ <%= status_report( @checkers ) %>
@@ -0,0 +1,7 @@
1
+ en:
2
+ status_cat:
3
+ h1: Status Report
4
+ name: Name
5
+ value: Value
6
+ status: Status
7
+ ok: OK
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ StatusCat::Engine.routes.draw do
2
+ root :to => 'status#index'
3
+ get '/status' => 'status#index'
4
+ end
@@ -0,0 +1,31 @@
1
+ module StatusCat
2
+ module Checkers
3
+ class ActionMailer < Base
4
+
5
+ def initialize
6
+ @value = "#{config[ :address ]}:#{config[ :port ]}"
7
+
8
+ unless ::ActionMailer::Base.delivery_method == :test
9
+ @status = fail_on_exception do
10
+ address = config[ :address ]
11
+ port = config[ :port ]
12
+ domain = config[ :domain ]
13
+ user_name = config[ :user_name ]
14
+ password = config[ :password ]
15
+ authentication = config[ :authentication ]
16
+
17
+ Net::SMTP.start( address, port, domain, user_name, password, authentication ) do |smtp|
18
+ smtp.send_message( '', StatusCat.config.from, StatusCat.config.noreply )
19
+ end
20
+ nil
21
+ end
22
+ end
23
+ end
24
+
25
+ def config
26
+ @config ||= ::ActionMailer::Base.smtp_settings
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ module StatusCat
2
+ module Checkers
3
+ class ActiveRecord < Base
4
+
5
+ def initialize
6
+ @value = "#{config[ :adapter ]}:#{config[ :username ]}@#{config[ :database ]}"
7
+
8
+ @status = fail_on_exception do
9
+ ::ActiveRecord::Base.connection.execute( "select max(version) from schema_migrations" )
10
+ nil
11
+ end
12
+ end
13
+
14
+ def config
15
+ unless @config
16
+ yaml = YAML::load( ERB.new( IO.read( File.join( Rails.root, 'config', 'database.yml' ) ) ).result )
17
+ @config = yaml[ Rails.env ].symbolize_keys!
18
+ end
19
+ return @config
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ module StatusCat
2
+ module Checkers
3
+ class Base
4
+ extend ActiveSupport::DescendantsTracker
5
+
6
+ FORMAT = "%s | %s | %s\n"
7
+
8
+ attr_reader :value, :status
9
+
10
+ def self.class_to_name( klass )
11
+ klass.to_s.split( '::' ).last.underscore.to_sym
12
+ end
13
+
14
+ def name
15
+ Base.class_to_name( self.class )
16
+ #self.class.to_s.split( '::' ).last.underscore.to_sym
17
+ end
18
+
19
+ def to_s( format = FORMAT )
20
+ sprintf( format, name, value, status || I18n.t( :ok, :scope => :status_cat ) )
21
+ end
22
+
23
+ protected
24
+
25
+ def fail_on_exception
26
+ begin
27
+ return yield
28
+ rescue Exception => e
29
+ return e
30
+ end
31
+
32
+ return nil
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,28 @@
1
+ module StatusCat
2
+ module Checkers
3
+
4
+ class DelayedJob < Base
5
+ include ActionView::Helpers::DateHelper
6
+
7
+ def initialize
8
+ if !defined?( ::Delayed )
9
+ @status = 'delayed_job gem not installed'
10
+ else
11
+ @status = fail_on_exception do
12
+ sql = 'select count(*) from delayed_jobs'
13
+ result = ::ActiveRecord::Base.connection.execute( sql ).first
14
+ @value = result.is_a?( Hash ) ? result[ 'count' ] : result[ 0 ]
15
+
16
+ expires = 1.day.ago
17
+ sql = "select count(*) from delayed_jobs where created_at < '#{expires.to_s( :db )}'"
18
+ result = ::ActiveRecord::Base.connection.execute( sql ).first
19
+ value = result.is_a?( Hash ) ? result[ 'count' ] : result[ 0 ]
20
+
21
+ ( value.to_i == 0 ) ? nil : "#{value} jobs more than #{time_ago_in_words( expires )} old"
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module StatusCat
2
+ module Checkers
3
+ class S3 < Base
4
+ def initialize
5
+ if !defined?( ::AWS )
6
+ @status = 'aws-sdk gem not installed'
7
+ else
8
+ @value = AWS.config.access_key_id
9
+ @status = fail_on_exception do
10
+ s3 = AWS::S3.new
11
+ ( s3.buckets.count > 0 ) ? nil : 'no buckets'
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module StatusCat
2
+ module Checkers
3
+
4
+ class Stripe < Base
5
+ def initialize
6
+ if !defined?( ::Stripe )
7
+ @status = 'stripe gem not installed'
8
+ else
9
+ @status = fail_on_exception do
10
+ account = ::Stripe::Account.retrieve()
11
+ @value = account.email
12
+ account.charge_enabled ? nil : 'Charge is not enabled'
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ require 'singleton'
2
+
3
+ module StatusCat
4
+
5
+ class Config
6
+ include Singleton
7
+
8
+ NIL_PROC = proc {}
9
+
10
+ attr_accessor :enabled
11
+ attr_accessor :authenticate, :authorize
12
+ attr_accessor :from, :to, :subject, :noreply
13
+ attr_accessor :layout
14
+
15
+ def initialize
16
+ @enabled = StatusCat::Checkers::Base.descendants.map { |klass|
17
+ StatusCat::Checkers::Base.class_to_name( klass )
18
+ }.sort
19
+ end
20
+
21
+ def authenticate_with(&blk)
22
+ @authenticate = blk if blk
23
+ @authenticate || NIL_PROC
24
+ end
25
+
26
+ def authorize_with(&block)
27
+ @authorize = block if block
28
+ @authorize || NIL_PROC
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,5 @@
1
+ module StatusCat
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace StatusCat
4
+ end
5
+ end
@@ -0,0 +1,37 @@
1
+ module StatusCat
2
+
3
+ class Status
4
+
5
+ # Returns an array of instances of StatusCat::Checkers::Base subclasses
6
+ def self.all
7
+ StatusCat::Config.instance.enabled.map { |name| factory( name ) }
8
+ end
9
+
10
+ # By default, returns all checkers
11
+ # If given a list of checker names, returns an array of those checkers
12
+ # If given a single checker name, just returns that checker
13
+ def self.check( which = :all )
14
+ return all if which == :all
15
+ return factory( which ) unless which.is_a?( Array )
16
+ return which.map { |name| factory( name ) }
17
+ end
18
+
19
+ # Emails ::failed list if it is not empty
20
+ def self.cron
21
+ checkers = self.failed
22
+ StatusCat::StatusMailer.failure( checkers ).deliver unless checkers.empty?
23
+ end
24
+
25
+ # Constructs a checker instance given it's name
26
+ def self.factory( name )
27
+ ( 'StatusCat::Checkers::' + name.to_s.classify ).constantize.new
28
+ end
29
+
30
+ # Returns an array of failed instances of ::all
31
+ def self.failed
32
+ self.all.map { |checker| checker.status.nil? ? nil : checker }.compact
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,3 @@
1
+ module StatusCat
2
+ VERSION = '0.0.8'
3
+ end