Wellness
A rack middleware library that adds a health check to your service. It comes with pre made services and has the option and flexibility for you to make your own.
Usage - Rails
There are some pre configured services that are provided with this gem. However, you must require them when you need them. This is because they have external dependencies that need to be loaded, that your application may not necessarily have.
module MySuperCoolApplication
class Application < Rails::Application
system = Wellness::System.new('my-super-cool-app')
service = Wellness::Services::PostgresService.new({
host: ENV['POSTGRESQL_HOST'],
port: ENV['POSTGRESQL_PORT'],
database: ENV['POSTGRESQL_DATABASE'],
user: ENV['POSTGRESQL_USERNAME'],
password: ENV['POSTGRESQL_PASSWORD']
})
system.add_service('database', service, { critical: true })
service = Wellness::Services::RedisService.new({
host: ENV['REDIS_HOST']
})
system.add_service('redis', service, { critical: false})
config.middleware.insert_before('::ActiveRecord::QueryCache', 'Wellness::Middleware', system)
end
end
Usage - Sinatra
require 'wellness'
system = Wellness::System.new('my-super-cool-app')
service = Wellness::Services::PostgresService.new({
host: ENV['POSTGRESQL_HOST'],
port: ENV['POSTGRESQL_PORT'],
database: ENV['POSTGRESQL_DATABASE'],
user: ENV['POSTGRESQL_USERNAME'],
password: ENV['POSTGRESQL_PASSWORD']
})
system.add_service('database', service, { critical: true })
service = Wellness::Services::RedisService.new({
host: ENV['REDIS_HOST']
})
system.add_service('redis', service, { critical: false})
use(Wellness::Middleware, system)
Example Responses
{
"status": "UNHEALTHY",
"details": {
"git" : {
"revision" : "1234567"
}
},
"dependencies":{
"database":{
"status":"UNHEALTHY",
"details":{
"error":"no response from ping"
}
},
"sidekiq":{
"status":"HEALTHY",
"details":{
"processed":0,
"failed":0,
"busy":0,
"enqueued":0,
"scheduled":0,
"retries":0,
"default_latency":0,
"redis":{
"uptime_in_days":"0",
"connected_clients":"1",
"used_memory_human":"979.22K",
"used_memory_peak_human":"1.02M"
}
}
}
}
}
{
"status": "HEALTHY",
"services": {
"postgresql": {
"status": "HEALTHY",
"details": { }
},
"mysql": {
"status": "HEALTHY",
"details": { }
}
},
"details": {
"git": {
"revision": "1234567"
}
}
}
Custom Services
Creating a custom service is super easy. As long as the service responds to
#call
, you are just fine. Passing a lambda
or Proc
is perfectly
acceptable.
Requirements
This interface has a few requirements.
- A service MUST respond to
#call
- A hash MUST be returned
- The hash returned MUST contain a
status
key at the root level. - Status can ONLY be
HEALTHY
,UNHEALTHY
, andDEGRADED
- All hash keys MUST be strings
Example
module MyServices
class MySQLService
def initialize(args={})
@connection_options = {
host: args[:host],
port: args[:port],
database: args[:database],
username: args[:username],
password: args[:password]
}
end
def healthy(details={})
{
'status' => 'HEALTHY',
'details' => details
}
end
def unhealthy(details={})
{
'status' => 'UNHEALTHY',
'details' => details
}
end
def call
connection = Mysql2::Client.new(@connection_options)
connection.ping ? healthy : unhealthy
rescue Mysql2::Error => error
unhealthy('error' => error.)
end
end
end
system = Wellness::System.new('my-app')
system.use('mysql', MyServices::MySQLService.new({
# ... configuration ...
}))
Custom Details
Details are useful if you want to display information on an application like the current git revision, or how many requests have been serviced by the application.
Requirements
- A detail MUST respond to
#call
- A hash MUST be returned
- All hash keys MUST be strings
Example
# Your custom detail component
module MyDetails
class GitRevisionDetail
def call
{
'revision' => revision
}
end
def revision
`git rev-parse --short HEAD`.chomp
end
end
end
# Initialize the wellness system
system = Wellness::System.new('my-app')
system.use('git', MyDetails::GitRevisionDetail.new)
# Load it into your rack
use(Wellness::Middleware, system)
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request