Class: Outpost::Scout Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/outpost/scout.rb

Overview

This class is abstract.

Subclasses must override #setup and #execute to be a valid Scout

Scouts are responsible for gathering data about a something specific that is a part of your system. For example, a HTTP Scout is responsible for getting the response code (200 for OK, 404 for Page Not Found, etc.), response body and any other thing you might want to know.

Scouts must also contain expectations. They must be registered into the Scout that wish to support different types of expectations. You can supply a block or an object that respond to #call and return true if any of the rules match. It will receive an instance of the scout (so you can query current system state) as the first parameter and the state defined by the Outpost as the second.

Example:

expect(:response_code) do |scout, code|
  scout.response_code == code
end

Scouts may also report specific data. This is useful to complement status reporting with the data received from the measurement. After the scout is run, each report data method will be executed and its calue will be added to the resulting report.

Examples:

an example of a Scout that parses the HTTP response code

module Outpost
  module Scouts
    class Http < Outpost::Scout
      expect(:response_code) { |scout,code| scout.response_code == code }

      attr_reader :response_code

      def setup(options)
        @host = options[:host]
        @port = options[:port] || 80
        @path = options[:path] || '/'
      end

      def execute
        response = Net::HTTP.get_response(@host, @path, @port)
        @response_code = response.code.to_i
      end
    end
  end
end

an example of a Scout that reports the duration of a HTTP request

module Outpost
  module Scouts
    class TimedHttp < Outpost::Scout
      expect(:response_code) { |scout,code| scout.response_code == code }

      attr_reader :response_code, :response_time
      report_data :response_time

      def setup(options)
        @host = options[:host]
        @port = options[:port] || 80
        @path = options[:path] || '/'
      end

      def execute
        previous_time = Time.now

        response = Net::HTTP.get_response(@host, @path, @port)
        @response_code = response.code.to_i

        @response_time = Time.now - response_time
      end
    end
  end
end

Direct Known Subclasses

Outpost::Scouts::Http, Outpost::Scouts::Ping

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(description, config) ⇒ Scout


128
129
130
131
132
133
134
# File 'lib/outpost/scout.rb', line 128

def initialize(description, config)
  @description = description
  @config      = config
  @report_data = {}

  setup(config.options)
end

Class Attribute Details

.reporting_data_methodsObject (readonly)

Returns the value of attribute reporting_data_methods


81
82
83
# File 'lib/outpost/scout.rb', line 81

def reporting_data_methods
  @reporting_data_methods
end

Instance Attribute Details

#report_dataObject (readonly)

Returns the value of attribute report_data


78
79
80
# File 'lib/outpost/scout.rb', line 78

def report_data
  @report_data
end

Class Method Details

.expect(expectation, callable = nil, &callable_block) ⇒ Object

Registers a new expectation into the Scout. If the callable does not respond to #call, an ArgumentError will be raised.

Raises:

  • (ArgumentError)

    raised when the callable parameter does not respond to #call method.


102
103
104
105
106
107
108
109
110
111
# File 'lib/outpost/scout.rb', line 102

def expect(expectation, callable=nil, &callable_block)
  callable ||= callable_block

  if callable.respond_to?(:call)
    @expectations ||= {}
    @expectations[expectation] = callable
  else
    raise ArgumentError, 'Object must respond to method #call to be a valid expectation.'
  end
end

.expectationsHash<Symbol, Object>

Returns the hash of expectations, where the key is the name of the expectation and the value is the callable Object (object that responds to #call)


88
89
90
# File 'lib/outpost/scout.rb', line 88

def expectations
  @expectations ? @expectations.dup : {}
end

.report_data(*methods) ⇒ Object


118
119
120
121
# File 'lib/outpost/scout.rb', line 118

def report_data(*methods)
  @reporting_data_methods ||= []
  @reporting_data_methods += methods
end

Instance Method Details

#execute(*args) ⇒ Object

Called when the Scout must take action and gather all the data needed to be analyzed.

Raises:

  • (NotImplementedError)

    raised when method is not overriden.


192
193
194
# File 'lib/outpost/scout.rb', line 192

def execute(*args)
  raise NotImplementedError, 'You must implement the execute method for Scout to work correctly.'
end

#gather_reporting_dataObject


170
171
172
173
174
175
176
177
178
# File 'lib/outpost/scout.rb', line 170

def gather_reporting_data
  self.class.reporting_data_methods.each do |method|
    if respond_to?(method)
      @report_data[method.to_sym] = send(method)
    else
      raise ArgumentError,  "Scout #{self.class.name} does not respond to ##{method} reporting data method"
    end
  end
end

#runSymbol

Executes the Scout and go through all the registered expectations to find out all expectations that match and return the associated status.

Raises:

  • (NotImplementedError)

    raised when a configured expectation was not registered in the Scout.


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/outpost/scout.rb', line 142

def run
  statuses = []
  execute
  # Response_pair contains the expectation as key and the expected value as
  # value.
  # Example: {:response_time => 200}
  #
  # status is the status (:up, :down or :warning, for example) that will be returned
  # in case the expectation match current system status.
  if @config.reports && !@config.reports.empty?
    @config.reports.each do |response_pair, status|
      response_pair.each do |expectation, value|
        if self.class.expectations[expectation].nil?
          message = "expectation '#{expectation}' wasn't implemented by #{self.class.name}"
          raise NotImplementedError, message
        end

        if self.class.expectations[expectation].call(self, value)
          statuses << status
        end
      end
    end
  end

  gather_reporting_data
  Report.summarize(statuses)
end

#setup(*args) ⇒ Object

Called when the scout object is being constructed. Arguments can be everything the developer set in the creation of Outpost.

Raises:

  • (NotImplementedError)

    raised when method is not overriden.


184
185
186
# File 'lib/outpost/scout.rb', line 184

def setup(*args)
  raise NotImplementedError, 'You must implement the setup method for Scout to work correctly.'
end