Git Product home page Git Product logo

okcomputer's Introduction

Code Climate Build Status

OK Computer

Inspired by the ease of installing and setting up fitter-happier as a Rails application's health check, but frustrated by its lack of flexibility, OK Computer was born. It provides a robust endpoint to perform server health checks with a set of built-in plugins, as well as a simple interface to add your own custom checks.

For more insight into why we built this, check out our blog post introducing OK Computer.

OkComputer currently supports the following Rails versions:

  • 7.0
  • 6.1
  • 6.0
  • 5.2
  • 5.1
  • 4.2

Not using Rails?

If you use Grape instead of Rails, check out okcomputer-grape.

Installation

Add this line to your application's Gemfile:

gem 'okcomputer'

And then execute:

$ bundle

Or install it yourself as:

$ gem install okcomputer

Usage

To perform the default checks (application running and ActiveRecord database connection), do nothing other than adding to your application's Gemfile.

If Not Using ActiveRecord

We also include a MongoidCheck, but do not register it. If you use Mongoid, replace the default ActiveRecord check like so:

OkComputer::Registry.register "database", OkComputer::MongoidCheck.new

If you use another database adapter, see Registering Custom Checks below to build your own database check and register it with the name "database" to replace the built-in check, or use OkComputer::Registry.deregister "database" to stop checking your database altogether.

Requiring Authentication

Optionally require HTTP Basic authentication to view the results of checks in an initializer, like so:

# config/initializers/okcomputer.rb
OkComputer.require_authentication("username", "password")

To allow access to specific checks without a password, optionally specify the names of the checks:

# config/initializers/okcomputer.rb
OkComputer.require_authentication("username", "password", except: %w(default nonsecret))

Changing the OkComputer Route

By default, OkComputer routes are mounted at /okcomputer. If you'd like to use an alternate route, you can configure it with:

# config/initializers/okcomputer.rb
OkComputer.mount_at = 'health_checks'    # mounts at /health_checks

For more control of adding OkComputer to your routes, set OkComputer.mount_at = false to disable automatic mounting, and you can manually mount the engine in your routes.rb.

# config/initializers/okcomputer.rb
OkComputer.mount_at = false

# config/routes.rb, at any priority that suits you
mount OkComputer::Engine, at: "/custom_path"

Logging check results

Log check results by setting OkComputer.logger. Note: results will be logged at the info level.

OkComputer.logger = Rails.logger
[okcomputer] mycheck: PASSED mymessage (0s)

Registering Additional Checks

Register additional checks in an initializer, like so:

# config/initializers/okcomputer.rb
OkComputer::Registry.register "resque_down", OkComputer::ResqueDownCheck.new
OkComputer::Registry.register "resque_backed_up", OkComputer::ResqueBackedUpCheck.new("critical", 100)

# This check works on 2.4.0 and above versions of resque-scheduler
OkComputer::Registry.register "resque_scheduler_down", OkComputer::ResqueSchedulerCheck.new

Registering Custom Checks

The simplest way to register a check unique to your application is to subclass OkComputer::Check and implement your own #check method, which sets the display message with mark_message, and calls mark_failure if anything is wrong.

# config/initializers/okcomputer.rb
class MyCustomCheck < OkComputer::Check
  def check
    if rand(10).even?
      mark_message "Even is great!"
    else
      mark_failure
      mark_message "We don't like odd numbers"
    end
  end
end

OkComputer::Registry.register "check_for_odds", MyCustomCheck.new

Registering Optional Checks

Register an optional check like so:

# ...
OkComputer::Registry.register "some_optional_check", OkComputer::ResqueBackedUpCheck.new("critical", 100)
# ...

OkComputer.make_optional %w(some_optional_check another_optional_check)

This check will run and report its status, but will not affect the HTTP status code returned.

Customizing plain-text output

The plain-text output flows through Rails' internationalization framework. Adjust the output as necessary by defining okcomputer.check.passed and okcomputer.check.failed keys in your setup. The default values are available in okcomputer.en.yml.

Running checks in parallel

By default, OkComputer runs checks in sequence. If you'd like to run them in parallel, you can configure it with:

# config/initializers/okcomputer.rb
OkComputer.check_in_parallel = true

Performing Checks

Checks are available as plain text (by default) or JSON by appending .json, e.g.:

OkComputer NewRelic Ignore

If NewRelic is installed, OkComputer automatically disables NewRelic monitoring for uptime checks, as it will start to artificially bring your request time down.

If you'd like to intentionally count OkComputer requests in your NewRelic analytics, set:

# config/initializers/okcomputer.rb
OkComputer.analytics_ignore = false

Development

Setup

$ bundle install

Running the test suite

OkComputer tests are written with RSpec.

To run the full test suite:

$ rake spec

You may also use the environment variable RAILS_VERSION with one of the supported versions of Rails (found at the top of this file) to bundle and run the tests with a specific version of Rails.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

okcomputer's People

Contributors

agacode avatar aryk avatar cbeer avatar chrisarcand avatar darbyfrey avatar dwbutler avatar ehlertij avatar ekampp avatar elliothursh avatar elliott-beach avatar evanlok avatar f1sherman avatar henare avatar johnnyshields avatar jphenow avatar kruppel avatar leoasis avatar lyleunderwood avatar natejgreene avatar ndushay avatar newzac avatar nrodriguez avatar olleolleolle avatar onomated avatar owst avatar pbyrne avatar priverop avatar rmm5t avatar sergeyevstifeev avatar stevendaniels avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

okcomputer's Issues

Wrong JSON behaviour for routes

I tested this behaviour on Rails 4.2 and 4.1

According to the documentation a GET to /okcomupter.json will return a 200 OK with a JSON response. However on Rails 4.1 and 4.2 I will get a 404

curl -I http://localhost:3001/okcomputer.json

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Content-Length: 12454
X-Request-Id: 3f1c178b-008c-4a10-b706-a558dca5970b
X-Runtime: 0.131676
Server: WEBrick/1.3.1 (Ruby/2.2.0/2014-12-25)
Date: Fri, 09 Jan 2015 11:49:07 GMT
Connection: Keep-Alive

Request to /okcomputer/all.json is working though.

Furthermore I would expect setting the content type header to "application/json" would also reply with a json response but it doesn't.

curl -H "Content-Type: application/json" http://localhost:3001/okcomputer/all
default: PASSED Application is running
database: PASSED Schema version: 0

tested it on an empty app with zero configuration (only gem "okcomputer" in Gemfile)

Basic Auth should apply to advanced routes only

In general I think it's fine to not protect the basic "default: PASSED Application is running" message. The Basic Authentication password should be applied only to the advanced routes, e.g. /ok_computer/all

Thoughts?

Enhance AppVersionCheck

Suggestion: Enhance the constructor of OkComputer::AppVersionCheck to accept file and env arguments to configure which file path and ENV var to look for. Default to "REVISION" and "SHA" respectively.

I plan to submit a PR with this enhancement soon.

On First Failure, Can Still Respond with 200

On the first failure of a check, the text indicates a problem, but the HTTP response is 200. Subsequent checks have a 500 response as they should.

This should respond with 500 on the first failure.

Splitting out okcomputer-contrib

We've discussed this in the past, but I'm making an issue for more concentrated conversation. The gem has a lot of tool-specific checks (Resque, Sidekiq, and Delayed Job, and Mongoid) in addition to more generic checks. This raises two questions:

  • Does it make sense to split out the tool-specific checks into okcomputer-contrib (which is also freer to include more and more tool-specific checks and go really hog-wild)? Or maybe even okcomputer-resque and so on?
  • If that makes sense, does it make sense to do this before bumping to 1.0 and get it all done with?

Unhandled exception PG::Error

When using the ActiveRecord check with Rails 5.2.2 and pg 1.0.0, the database check (https://github.com/sportngin/okcomputer/blob/master/lib/ok_computer/built_in_checks/active_record_check.rb) will raise a PG::Error, instead of providing a clean "failed" output, if the database is shutdown.

I'm not 100% exactly sure yet why this is happening. PG::Error inherits from StandardError if I read well, so the rescue should work.

That said a reconnection by AR is happening, and may explain that.

Here is the full stack trace:

Started GET "/health-checks/all" for ::1 at 2019-01-25 18:44:28 +0100
  
PG::Error (could not connect to server: Connection refused
	Is the server running on host "localhost" (::1) and accepting
	TCP/IP connections on port 5432?
could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP/IP connections on port 5432?
):
  
activerecord (5.2.2) lib/active_record/connection_adapters/postgresql_adapter.rb:706:in `set_client_encoding'
activerecord (5.2.2) lib/active_record/connection_adapters/postgresql_adapter.rb:706:in `configure_connection'
activerecord (5.2.2) lib/active_record/connection_adapters/postgresql_adapter.rb:266:in `block in reconnect!'
/Users/thbar/.rbenv/versions/2.5.3/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
activerecord (5.2.2) lib/active_record/connection_adapters/postgresql_adapter.rb:263:in `reconnect!'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract_adapter.rb:435:in `verify!'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:860:in `block in checkout_and_verify'
activesupport (5.2.2) lib/active_support/callbacks.rb:132:in `run_callbacks'
activesupport (5.2.2) lib/active_support/callbacks.rb:816:in `_run_checkout_callbacks'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:859:in `checkout_and_verify'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:523:in `checkout'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:382:in `connection'
activerecord (5.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:1010:in `retrieve_connection'
activerecord (5.2.2) lib/active_record/connection_handling.rb:118:in `retrieve_connection'
activerecord (5.2.2) lib/active_record/connection_handling.rb:90:in `connection'
activerecord (5.2.2) lib/active_record/migration.rb:554:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (5.2.2) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (5.2.2) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
rollbar (2.16.2) lib/rollbar/middleware/rails/rollbar.rb:24:in `block in call'
rollbar (2.16.2) lib/rollbar.rb:146:in `scoped'
rollbar (2.16.2) lib/rollbar/middleware/rails/rollbar.rb:22:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
rollbar (2.16.2) lib/rollbar/middleware/rails/show_exceptions.rb:22:in `call_with_rollbar'
web-console (3.4.0) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.4.0) lib/web_console/middleware.rb:28:in `block in call'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `catch'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.2) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.2) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.2) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.2) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.2) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.2) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
request_store (1.4.1) lib/request_store/middleware.rb:19:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.6) lib/rack/method_override.rb:22:in `call'
rack (2.0.6) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.2) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.2) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.6) lib/rack/sendfile.rb:111:in `call'
railties (5.2.2) lib/rails/engine.rb:524:in `call'
rack (2.0.6) lib/rack/handler/webrick.rb:86:in `service'
/Users/thbar/.rbenv/versions/2.5.3/lib/ruby/2.5.0/webrick/httpserver.rb:140:in `service'
/Users/thbar/.rbenv/versions/2.5.3/lib/ruby/2.5.0/webrick/httpserver.rb:96:in `run'
/Users/thbar/.rbenv/versions/2.5.3/lib/ruby/2.5.0/webrick/server.rb:307:in `block in start_thread'

Order of checks

Hi again!

In my current use case where I'm using this gem, I need to have some sort of defined order of the checks, since there is one specific check whose result depends in the result of the rest of the checks (if all ok, then this check is OK, otherwise some other stuff). Also, this specific check needs to be shown first in the list (not needed in json, but it is needed for text output).

So I've been thinking of a feature to add that would be the order (or priority?) of a check. In fact, it would have 2 orders, one to show and one to run.

I currently have some code that manages this where I'm using this, so if you are interested in incorporating this feature let me know and I can create a PR with this.

stacktrace from CheckCollection internals

version: 1.14.1

configuration:

# config/initializers/okcomputer.rb
OkComputer::Registry.register :sidekiq_latency_check, OkComputer::SidekiqLatencyCheck.new(:default, 60)

stacktrace:

ArgumentError: comparison of OkComputer::ActiveRecordCheck with OkComputer::SidekiqLatencyCheck failed
  from ok_computer/check_collection.rb:85:in `sort'
  from ok_computer/check_collection.rb:85:in `to_text'
  from action_controller/metal/rendering.rb:116:in `block in _normalize_text'
  from action_controller/metal/rendering.rb:114:in `each'
  from action_controller/metal/rendering.rb:114:in `_normalize_text'
  from action_controller/metal/rendering.rb:84:in `_normalize_options'
  from abstract_controller/rendering.rb:128:in `_normalize_render'
  from abstract_controller/rendering.rb:25:in `render'
  from action_controller/metal/rendering.rb:36:in `render'
  from action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render'
  from active_support/core_ext/benchmark.rb:12:in `block in ms'
  from benchmark.rb:308:in `realtime'
  from active_support/core_ext/benchmark.rb:12:in `ms'

Check name missing when in CheckCollection

When registering a Check to a CheckCollection using the register instance method, the Check's name does not get set as it does when using the Registry's register class method. This causes the output to look like:

Standard Checks
: PASSED Application is running (0s)
: PASSED Schema version: 20161208191710 (0s)
: PASSED Ruby 2.3.4-p301 (0s)

and the JSON output to have only one messge:

{"":{"message":"Ruby 2.3.4-p301","success":true,"time":5.672976840287447e-06}}

On Rails 4.2, authentication doesn't seem to take effect.

I have basic auth enabled via my initializer okcomputer.rb:

puts "requite basic auth via #{Rails.application.secrets.active_resource_user_name}"
# doesn't appear to be working...
OkComputer.require_authentication(Rails.application.secrets.active_resource_user_name, Rails.application.secrets.active_resource_user_password)

I see the puts, but I don't get prompted for the basic auth when I got /okcomputer, it just runs it. Not a big deal. I'm on Rails 4.2, is that getting long in the tooth these days?

Root route not matching a check with Rails 5

Hi.

In the process of upgrading an app to Rails 5,
we noticed the root route health check returns a 404.

It seems the root route returns a No matching check.
/default, /all, and other checks pass:

$ curl localhost/okcomputer
No matching check

$ curl localhost/okcomputer/
No matching check

$ curl localhost/okcomputer/default
default: PASSED Application is running

$ curl localhost/okcomputer/all
default: PASSED Application is running
database: PASSED Schema version: 20160708002852
revision: PASSED Version: 89e03b2f82666d8a37f309b32528f101c9d614a0
ruby_version: PASSED Ruby 2.3.1-p112

Workaround is to call /okcomputer/default instead of /okcomputer

Also, thank you for this very handy gem ๐Ÿ‘

CheckGroup API

I'm planning out how to do check groups and wanted to get something down for how We think it should work. @newzac and I were thinking something like this

OkComputer::Registry.register_group "a-check-group", OkComputer::CheckGroup.new("My Check Group")

OkComputer::Registry.groups
# Things that aren't explicitly put in a check group end up in the default group
=> [CheckGroup("default"), CheckGroup("My Check Group")]

# Register a normal check with a group
OkComputer::Registry.register "group-check", OkComputer::Check.new, group: "a-check-group"
OkComputer::Registry.register "another-group-check", OkComputer::Check.new, group: "a-check-group"
# Register a normal check without a group
OkComputer::Registry.register "check", OkComputer::Check.new

# /okcomputer/all.text
default: PASSED Application is running
database: PASSED Schema version: 20161012191551
check: PASSED 
My Check Group:
  group-check: PASSED
  another-group-check: PASSED

#/okcomputer/a-check-group.text
group-check: PASSED
another-group-check: PASSED

#/okcomputer/group-check.text
group-check: PASSED

We're going to take a stab at this hopefully we come up with something reasonable. We're also planning to start duping checks on #run

All-Check JSON is Silly

The JSON in the all-check is an array of JSON objects each with one key. Really, it should be a single JSON object with multiple keys.

_bad_

[{"check": "result"}, {"other": "result"}]

_better_

{"check": "result", "other": "result"}

App Version Check

It would be nice to have a new built in check that tells you what version of the app you have deployed

HTTP code always 200 for specific check route if check is optional

I'm guessing this is by design, and can imagine without having looked at the code itself that this'd probably make for a more straightforward implementation, but wanted to ask anyway as I couldn't find any other issues mentioning this:

Are checks that are optional meant to return a success HTTP code when accessing them directly?

The situation I'm in is that we have an application using Elasticsearch to power its search - if this goes down (or is not accessible for some reason), the search stops working but the rest of the site is still up. So we've got a few monitors setup based on use-case:

  • Our load balancer is configured to use the standard /healthchecks route, since for autoscaling we only care if the app is "up" or not
  • We have a downtime monitor checking /healthchecks/all to tell us if something "critical" is down (which really for this app is just "is the app up + the database accessible", since that's the only other extra service besides Elasticsearch)
  • We have another downtime monitor checking /healthchecks/elasticsearch to tell us if the service is down, without classing the whole site as being down.
    • However, currently it seems that this returning 200 even if the check fails

My thinking was that marking the elasticsearch healthcheck as optional would mean it wouldn't fail /healthchecks/all, but I still expected it to fail it's specific route, since tbh otherwise I don't see there being much point in that route (ignoring that I could arguably do text matching, as that isn't always supported + can be more brittle).

On the other hand, maybe I'm just using this wrong?

Issue using CacheCheck

Hi,

The CacheCheck looks great, but I can't use it out-of-the-box because of this line:

host = stats.select{|k,v| k =~ Regexp.new(Socket.gethostname) }.values[0]

It took me a while to figure out what this is doing, but I managed to hypothesize that you are running a memcache node locally on each app server. This is different from what I'm used to: a memcache cluster living entirely separately from the app servers.

So this line will always fail if your memcache server is separate from your app server (or if Socket.gethostname reports something that doesn't match). Think Amazon Elasticache or Memcachier on Heroku.

I'm not sure what the best solution is, but I would be in favor of turning this into a more generic check for connectivity between app and the memcached server. Reporting RAM usage is kind of cool, but may not mean a whole lot since one expects memcached to fill up and start evicting things.

It might also make sense to rename this to MemcachedCheck to make it clear that it only works with memcached. A more generic check might just try reading/writing from the cache.

Proposal: allow running healtchecks in parallel

Currently the healthchecks are run in sequence:

# Public: Run the registry's checks
def run
  checks.each(&:run)
end

this presents an issue for us as we have a constantly growing number of healthchecks but we also want to have a fixed known timeout for all healthchecks to be completed. It would be great to allow to run the healthchecks in parallel. What do you think?
I can create a pull request if you think this is a reasonable suggestion.

Ruby 1.9.3, Rails 4.2.7.1, stacktrace after bundle update

$ bundle exec rake --tasks                                  rake aborted!
SyntaxError: /home/user/.rvm/gems/ruby-1.9.3-p484/gems/okcomputer-1.11.1/lib/ok_computer/legacy_rails_controller_support.rb:13: syntax error, unexpected tPOW, expecting ')'
    def render(**options, &block)
                 ^
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/okcomputer-1.11.1/lib/ok_computer/legacy_rails_controller_support.rb:18: syntax error, unexpected keyword_end, expecting $end
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in `require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in `block in require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/activesupport-4.2.7.1/lib/active_support/dependencies.rb:274:in `require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/okcomputer-1.11.1/lib/okcomputer.rb:6:in `<top (required)>'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:86:in `block (2 levels) in require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `each'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:81:in `block in require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `each'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler/runtime.rb:70:in `require'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/bundler-1.12.5/lib/bundler.rb:102:in `require'
/user/repositories/tracking_notification/config/application.rb:8:in `<top (required)>'
/user/repositories/tracking_notification/Rakefile:5:in `require'
/user/repositories/tracking_notification/Rakefile:5:in `<top (required)>'
/home/user/.rvm/gems/ruby-1.9.3-p484/gems/rake-11.3.0/exe/rake:27:in `<top (required)>'
/home/user/.rvm/gems/ruby-1.9.3-p484/bin/ruby_executable_hooks:15:in `eval'
/home/user/.rvm/gems/ruby-1.9.3-p484/bin/ruby_executable_hooks:15:in `<main>'

What to do now?

Skip Database check.

Hello! Is it possible to skip the database check on '/all'? I'm not using database in a current project, only redis.

Thanks! Great gem

Thread safety

Overall, thread safety is really a big issue in this gem. Which, you could argue is "okish", since fails can be returned only when one of racing checks returns a false.

I've only been using a few checks and I've noticed a rather big issue with GenericCacheCheck though. When 2 checks hit a multi threaded application, the values saved in the key shared by both threads will be random, which will very likely cause a fail when reading them back. I am solving this temporarily with a mutex, since I am not sure whether you'd prefer to generate a more unique key (which could potentially lead to things being left over in a cache store) or a mutex.

Headers with "Accept: application/json" still renders in text format

Hey!

Nice gem, especially the name ๐Ÿ‘. I was trying to make the response be a json via headers, but I keep getting just text. If I add a route without the default text format, this works as expected, but then it is not accessible via GET in the browser since it sends Accept: text/html, and it needs text/plain to work with it.

Perhaps the fix is to be more explicit in the response formats and not relying in respond_with.

Also, just as a side note, when are you releasing 0.3.0? I could really use the new JSON output :D

Extract non-Rails bits into okcomputer-core

Following up on #85 (and by extension #83), I think it'd be straightforward to extract the guts of the gem into something like okcomputer-core, which could be used by others to build OK Computer for whichever tool they're using, be it Rack or Grape or Sinatra or what-have-you. Maybe even a command-line app?

Related to this effort would be a few questions:

  • Should we deprecate okcomputer and build okcomputer-rails to make it clear that this is merely the Rails implementation of the idea?
    • One risk to this plan would be getting everybody to use the newly named gem.
  • Already discussed in #56, we could split out the more esoteric checks into okcomputer-contrib which contains all the optional checks for things like Resque or Sidekiq or whatnot.
  • Is it reasonable for okcomputer-core to enable the DB check by default? Probably not, since ActiveRecord can no longer be presumed. Or do we alter altogether how the default checks are set-up, leaving that decision to the gem which integrates it into their app server?

Once okcomputer-core is available, ping @darbyfrey so he can use that rather than this gem in https://github.com/bellycard/okcomputer-grape.

Easier test running

In #96 I removed the default fallback of choosing the most recent supported version of Rails when running tests. Instead, you must specify a Rails version to test against when running tests.

This was intended to make CI fail harder when it's given a version of Rails in the build matrix it doesn't recognize, but has the unintended consequence of making running local tests slightly more cumbersome during development.

I'd like it if tests were easier to run for humans (by defaulting to the highest supported version of Rails, able to be overwritten by the environment variable) while still requiring explicit declaration in Travis.

Allow verbose on root route

I wanted to know what you thought about allowing a config to turn on verbose reporting for the root route instead of having to use /all. We have other applications which report on /healthcheck/status.json and I would like to have that route report the verbose output all would give me.

Ruby 2.3.1 deprecation warning in HttpCheck

I'm getting this deprecation warning when running under Ruby 2.3.1:

vendor/gems/ruby-2.3.1/gems/okcomputer-1.11.0/lib/ok_computer/built_in_checks/http_check.rb:37:in `perform_request': 
Object#timeout is deprecated, use Timeout.timeout instead.

Configuration option to force SSL?

I was planning to expose a health check protected by basic auth. Our application unfortunately does not force SSL. So if the health check is pinged over HTTP, the username and password will be sent in the clear over and over.

My thought was for OkComputer to expose a configuration option to force SSL. This in turn would call force_ssl on the OkComputerController.

Thoughts?

Support Rails 5.2 migrations check

Rails 5.2 fails the migrations check

This version of ActiveRecord does not support checking whether migrations are pending

ActiveRecord 5.1 (and prior) checked like so:

ActiveRecord::Migrator.needs_migration?

But ActiveRecord 5.2 needs to check like so:

ActiveRecord::Base.connection.migration_context.needs_migration?

I'll try to find the time to get a backwards compatible PR out soon, but I wanted to open this up for discussion first.

Automatically adding json format to custom mount route

When mounting OkComputer on a custom route via the mount_at config it is not immediately obvious that you must provide the format route parameter such as OkComputer.mount_at = 'healthcheck/status(.:format)'.

In the documentation it states that for the default route:

Checks are available as plain text (by default) or JSON by appending .json

I assumed that this would apply the formatters to the custom mount_at route, perhaps it is a misunderstanding on my part. I am opening this issue to suggest that (.:format) either be appended by default if not provided or to update the readme to be more clear. I'm happy to do either.

Specs fail under Rails 6.1.x

The specs are currently failing under Rails 6.1, but they pass under Rails 6.0.

  1. Edit the build matrix to get specs passing for Rails 5.1.x, 5.2.x and 6.0.x.
  2. Add support for Rails 6.1.x

Rails 5 support

Based on this attempt to run against Rails 5, it looks like we have a bit of work ahead of us to get the gem to work with Rails 5.

The main trouble seems to be the following error showing up against a lot of tests:

Failure/Error: controller.class.skip_before_filter :authenticate

ArgumentError:
  Before process_action callback :authenticate has not been defined

Missing requirement: responders

I started using okcomputer for my rails app (Rails 4.2.0).

As Rails 4.2. doesn't ship with the responders gem it needs to be added to the Gemfile separately:

gem "responders", "~> 2.0"
gem "okcomputer"

I don't know if it's possible to make it a requirement only for newer rails versions.

But anyway I think it should be part of the documentation

Checks pass even if the server is out of disk space

Even if my server is out of disk space and the application is returning 500s for every page, it still returns 200 for the okcomputer health check endpoints.

You can test this by creating a file that takes up as much space as you have left...

1. df (get disk space available... say 123456)
2. dd if=/dev/zero of=./testoutofspace bs=1024 count=123456
3. df (make sure we're out of disk space)
4. go to any valid app endpoint that isn't the health check and it will fail
5. go to the health check endpoint and it will pass

Maybe we should be running some type of Rails command when going to the endpoint? Or creating a custom endpoint that does this? Just throwing out ideas.

OK Computer 2.0 Brainstorming

Looking for ideas that people have been putting off for being backward incompatible. What annoys you about the current setup? What do you wish OK Computer could do that it doesn't do now? What do you wish could be easier?

Include errored/locked jobs in Delayed Job backup check

I think we should include errored/locked jobs in the DJ backup check. In other words this:

Delayed::Job.where("priority <= ?", priority).where(:locked_at => nil, :last_error => nil).count

should be:

Delayed::Job.where("priority <= ?", priority).count

Thoughts?

Incorrect error status?

Hi.

As far as I can see from OkComputer::OkComputerController, status might be either :ok, or :error.
Well, suppose we've got an issue there, because in the current Rack::Utils there are no such a status like "error" (https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L504), and if page renders with such a symbolic status, Rack::Utils cannot get a code for that and drops ArgumentError (Unrecognized status code :error).

Locally in my project I've just made a patch to rename this status to internal_server_error, because all my necessary check info is already in page body. Maybe we should do the same? Or just declare a usable list of symbolic error codes to pass them from the checks?

Ready to prepare a PR with renaming.

Mongoid check broken on Mongoid 5.0

undefined method `[]' for #Mongo::Operation::Result:0x007fb4692ca5e0

    # Returns a string with the mongdb name
    def mongodb_name
      mongodb_stats["db"] # <-- Errors here
    end

Error is in mongodb_stats method. session.command(dbStats: 1) should be session.command(dbStats: 1).first. So full method should look something like this:

    # Public: The stats for the app's mongodb
    #
    # Returns a hash with the status of the db
    def mongodb_stats
      if session
        stats = session.command(dbStats: 1) # Mongoid 3+
        stats = stats.first unless stats.is_a? Hash
        stats
      else
        Mongoid.database.stats # Mongoid 2
      end
    rescue => e
      raise ConnectionFailed, e
    end

Possible XSS vulnerability

When requesting a check that was not registered with OkComputer, OkComputer::Registry raises an error saying "No check registered with '#{check_name}'", which in turn gets rendered by the controller.

The check_name value is not escaped, so might include malicious contents, such as HTML, JS, or third-party code (PDF, Flash, etc), as part of a Cross-site Scripting attack.

Instead, you should probably either

  • Always escape user input (requested check name) when echoing back to the client, or
  • Avoid rendering the check name, replacing the error with a more generic "Check not found" message.

List of contributed checks?

Hi!

Sorry for posting a question 'bout procedure, but could not find any answer in the repo.

I just released ok_computer-clamav for checking a running ClamAV server process. I've been using this internally for years, it runs quite well.

Is there a list somewhere of third-party Checks I could add this to? Not sure how far the okcomputer-contrib has gone?

Abnormal Memory Increase?

We are monitoring memory usage with scoutapp for our rails app and we found the health check is causing some memory increase recently (see screenshots below)

Our setup

# routes.rb
mount OkComputer::Engine, at: "/health_check"
# config/initializers/okcomputer.rb
require 'okcomputer'

OkComputer.mount_at = false

Screenshots of memory usage

okcompuer_memory_1
okcompuer_memory_2
okcompuer_memory_3
okcompuer_memory_4
okcompuer_memory_5

Sequel Check?

Would you guys be ok to add a check for Sequel.

This should work for most use cases:

module OkComputer
  class SequelCheck < Check
    attr_reader :sequel_database, :migration_directory


    def initialize(sequel_database, migration_directory)
      @sequel_database = sequel_database
      @migration_directory = migration_directory
    end

    # Public: Return the schema version of the database
    def check
      mark_message "Schema is #{'not ' unless is_current?}up to date"
    rescue ConnectionFailed => e
      mark_failure
      mark_message "Error: '#{e}'"
    end

    # Public: The scema version of the app's database
    #
    # Returns a String with the version number
    def is_current?
      ::Sequel.extension(:migration)
      ::Sequel::Migrator.is_current?(sequel_database, migration_directory)
    rescue => e
      raise ConnectionFailed, e
    end

    ConnectionFailed = Class.new(StandardError)
  end
end

Then, user can do:

OkComputer::Registry.register "database", OkComputer::SequelCheck.new(::Sequel::Model.db, 'db/migrate')

Thoughts? A variation is you can put the ::Sequel.extension(:migration) at the top of the file. All it does is require one file.

I would fork, clone, pr and do all that, just thought this was relatively straightforward and maybe could avoid the extra work :)

Allow disabling a default check

Per #77, it'd be nice to be able to disable the default database check altogether, if wanted. Something like OkComputer::Registry.register "database", nil or OkComputer::Registry.unregister "database" could do the trick.

Cleanup for 1.0

In prep for releasing v1.0, let's tidy things up a bit give any new users of the app a clean slate. Feel free to add to this list.

  • Remove deprecation warnings and any code to support/detect old APIs
  • Are there general clarity improvements to be made in the README?
  • The "breaking changes" section of the README and the contents of UPDADING should be moved to CHANGELOG.markdown.
    • Should we backfill other pre-v1.0 changes into the CHANGELOG? I'm thinking not.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.