Class: IsItWorking::Handler

Inherits:
Object
  • Object
show all
Defined in:
lib/is_it_working/handler.rb

Overview

Rack handler that will run a set of status checks on the application and report the results. The results are formatted in plain text. If any of the checks fails, the response code will be 417 Expectation Failed.

The checks to perform are defined in the initialization block. Each check needs a name and can either be a predefined check, block, or an object that responds to the call method. When a check is called, its call method will be called with a Status object.

Example

IsItWorkingHandler.new do |h|
  # Predefined check to determine if a directory is accessible
  h.check :directory, "/var/myapp", :read, :write

  # Custom check using a block
  h.check :solr do
    SolrServer.available? ? ok("solr is up") : fail("solr is down")
  end
end

Constant Summary collapse

PATH_INFO =
"PATH_INFO".freeze

Instance Method Summary collapse

Constructor Details

#initialize(app = nil, route_path = "/is_it_working") {|_self| ... } ⇒ Handler

Create a new handler. This method can take a block which will yield itself so it can be configured.

The handler can be set up in one of two ways. If no arguments are supplied, it will return a regular Rack handler that can be used with a rackup run method or in a Rails 3+ routes.rb file. Otherwise, an application stack can be supplied in the first argument and a routing path in the second (defaults to /is_it_working) so it can be used with the rackup use method or in Rails.middleware.

Yields:

  • (_self)

Yield Parameters:



32
33
34
35
36
37
38
39
# File 'lib/is_it_working/handler.rb', line 32

def initialize(app=nil, route_path="/is_it_working", &block)
  @app = app
  @route_path = route_path
  @hostname = `hostname`.chomp
  @filters = []
  @mutex = Mutex.new
  yield self if block_given?
end

Instance Method Details

#call(env) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/is_it_working/handler.rb', line 41

def call(env)
  if @app.nil? || env[PATH_INFO] == @route_path
    statuses = []
    t = Time.now
    statuses = Filter.run_filters(@filters)
    render(statuses, Time.now - t)
  else
    @app.call(env)
  end
end

#check(name, *options_or_check, &block) ⇒ Object

Add a status check to the handler.

If a block is given, it will be used as the status check and will be yielded to with a Status object.

If the name matches one of the pre-defined status check classes, a new instance will be created using the rest of the arguments as the arguments to the initializer. The pre-defined classes are:

  • :action_mailer - Check if the send mail configuration used by ActionMailer is available

  • :active_record - Check if the database connection for an ActiveRecord class is up

  • :dalli - DalliCheck checks if all the servers in a MemCache cluster are available using dalli

  • :directory - DirectoryCheck checks for the accessibilty of a file system directory

  • :memcache - MemcacheCheck checks if all the servers in a MemCache cluster are available using memcache-client

  • :ping - Check if a host is reachable and accepting connections on a port

  • :url - Check if a getting a URL returns a success response



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/is_it_working/handler.rb', line 75

def check (name, *options_or_check, &block)
  raise ArgumentError("Too many arguments to #{self.class.name}#check") if options_or_check.size > 2
  check = nil
  options = {:async => true}
  
  unless options_or_check.empty?
    if options_or_check[0].is_a?(Hash)
      options = options.merge(options_or_check[0])
    else
      check = options_or_check[0]
    end
    if options_or_check[1].is_a?(Hash)
      options = options.merge(options_or_check[1])
    end
  end
  
  unless check
    if block
      check = block
    else
      check = lookup_check(name, options)
    end
  end
  
  @filters << Filter.new(name, check, options[:async])
end

#hostname=(val) ⇒ Object

Set the hostname reported the the application is running on. By default this is set the system hostname. You should override it if the value reported as the hostname by the system is not useful or if exposing it publicly would create a security risk.



55
56
57
# File 'lib/is_it_working/handler.rb', line 55

def hostname=(val)
  @hostname = val
end

#synchronizeObject

Helper method to synchronize a block of code so it can be thread safe. This method uses a Mutex and is not re-entrant. The synchronization will be only on calls to this handler.



105
106
107
108
109
# File 'lib/is_it_working/handler.rb', line 105

def synchronize
  @mutex.synchronize do
    yield
  end
end