Outpost is a service monitoring tool written purely on Ruby. It's main focus is to return a real-time service status using three structures: Scouts, Hooks and Outposts.
This is a very initial code, so any interface may change in time and may contain several bugs.
Outposts are Ruby classes that contains a DSL to express services dependencies. Example:
class WebOutpostExample < Outpost
depends WebScout => "web page" do
options :host => 'localhost', :port => 3000
report :up, :response_code => 200
report :up, :response_time => {:less_than => 100}
end
end
The above declared service will return a "up" status whenever the HTTP response code is 200 and the service response time is bellow 100 milliseconds.
Outpost relies on Scouts to do the determine a specific service's status, such as MySQL connection or HTTP servers' response.
Outpost gather all status reports and consolidate them by returning the highest
priority status. So if only one scout report a :down
status, the
overall system status will be :down
. The status list and their priority is as
follows (from lowest to highest priority):
:up
:warning
:unknown
:down
To learn more about consolidation, check
lib/outpost/scout/consolidation.rb
file, it's pretty
straightforward.
You can check a service's status by running the method #check!:
WebOutpostExample.new.check! # => :up
You can check more details about a service status by reading its messages:
outpost = WebOutExample.new
outpost.check!
outpost.messages.each do |message|
puts "#{message.scout_name} is #{message.status}: #{message.message}."
end
You can find more examples in the examples
folder.
Scouts are responsible to connect to the main service and return a basic status.
They receive options through initialization and must implement the
execute
method, which should return some sort of response.
By plugging hooks, Scouts may return service status based on response code or response time (included in the codebase). Example:
class WebScout < Scout::Base
add_hook Scout::Hooks::ResponseTime
add_hook Scout::Hooks::ResponseCode
attr_accessor :host, :port
def initialize(options = {})
@host = options[:host] || 'localhost'
@path = options[:path] || '/'
@port = options[:port] || 80
end
def execute
@message = Net::HTTP.get_response(@host, @path, @port).code.to_i
rescue StandardError => e
down!
@message = e.to_s
end
end
You may write your own hook classes. To learn how to do that, read the following subsection.
Hooks are a very simple classes that must implement the build_report
method.
It should return the service status depending on the rules. The example bellow
illustrates a very simple example:
class ResponseCode < Scout::Hooks::Base
def build_report(response, all_rules={})
responses = each_rule(all_rules, :response_code) do |rule, status|
if rule.is_a? Numeric or rule.is_a? String
status if rule.to_i == response.to_i
else
:unknown
end
end
end
end
The build_report
receives the response returned by the Scout and
all the rules specified on an Outpost. It is as follows:
{
:response_code => {
200 => :down
}
}
So each_rule
is a helper method that will iterate over all rules.
You can also implement two callbacks, before_measurement
and
after_measurement
in order to do anything you want before and
after the measurement, such as tracking time. These are optional.
Feel free to contact me personally, opening issues or pull requests.
Outpost is released under the MIT license.