heartcheck 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30402737433dacfa08875ade181a6fb9570b6b0a
4
+ data.tar.gz: d6747a981694289118544f929e70cb254153bdf4
5
+ SHA512:
6
+ metadata.gz: 3be0e45e564098d82e130030a69aaaca7c9858de1021629178745afd803db934f4ed439d9b9c580d67454519b950db42c082220b919992f8e08ae7336a6f73e7
7
+ data.tar.gz: d4129a1cf932d1ae0e3d724231dc03a0f7a02f158632318d372ee1c29f27cdc581c15983e1fdeafbe209711118769e29301b6a1ae131d9850b81a24991a319ab
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ $LOAD_PATH.push File.expand_path('../../lib', __FILE__)
6
+ require 'heartcheck'
7
+
8
+ optparse = OptionParser.new do |opts|
9
+ opts.banner = "Usage: heartcheck (rails|padrino|sinatra)\n\nYou can use flags as such:"
10
+
11
+ opts.on('-h', '--help', 'Display this screen') do
12
+ puts opts
13
+ exit
14
+ end
15
+
16
+ if ARGV.size != 1 || !%w(rails sinatra padrino).include?(ARGV[0])
17
+ puts opts
18
+ exit
19
+ end
20
+ end
21
+
22
+ begin
23
+ optparse.parse!
24
+ rescue OptionParser::InvalidOption => e
25
+ puts e
26
+ exit
27
+ end
28
+
29
+ Heartcheck::Generator.new(ARGV).invoke_all
@@ -0,0 +1,63 @@
1
+ require 'thor/group'
2
+
3
+ module Heartcheck
4
+ class Generator < Thor::Group
5
+ include Thor::Actions
6
+
7
+ desc 'generate default files and instructions to use the Heartcheck'
8
+
9
+ argument :framework
10
+
11
+ def self.source_root
12
+ File.join(File.dirname(__FILE__), 'templates')
13
+ end
14
+
15
+ def show_framework
16
+ box framework.capitalize, :green
17
+ end
18
+
19
+ def generate_initializer
20
+ template('config.rb', initializer_path)
21
+ end
22
+
23
+ def generate_route
24
+ case framework
25
+ when 'rails'
26
+ instructions(
27
+ 'config/routes.rb',
28
+ 'mount Heartcheck::App.new, at: "/monitoring"'
29
+ )
30
+ when 'padrino', 'sinatra'
31
+ instructions(
32
+ 'config.ru', %(require "heartcheck"
33
+ map "/monitoring" do
34
+ use Heartcheck::App
35
+ end)
36
+ )
37
+ end
38
+ end
39
+
40
+ def include_empty_lines
41
+ puts "\n\n"
42
+ end
43
+
44
+ private
45
+
46
+ def instructions(file_name, file_content)
47
+ box "Include the following content to file #{file_name}"
48
+ say file_content, :blue
49
+ end
50
+
51
+ def box(content, color = :red)
52
+ size = content.size
53
+ say "#{'=' * (size + 2)}\n #{content}\n#{'=' * (size + 2)}\n", color
54
+ end
55
+
56
+ def initializer_path
57
+ case framework
58
+ when 'rails' then 'config/initializers/heartcheck.rb'
59
+ when 'padrino', 'sinatra' then 'app/app.rb'
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,67 @@
1
+ Heartcheck.setup do |monitor|
2
+ # monitor has a default logger but you can use yours
3
+ # default value: Logger.new(STDOUT)
4
+ # monitor.logger = Rails.logger
5
+
6
+ # Services
7
+ # For each service you can set the folling options
8
+ # name: String => root name to show in report page (default: class.name)
9
+ # functional: Boolean => options to set if this service is optional (default: false)
10
+ # on_error: Block => to customize the errors (default: nil)
11
+ # to_validate: Block => to validate the sevices (default: nil)
12
+ #
13
+ # See the exemple bellow to undertand how you can configure it.
14
+ #
15
+ # monitor.add :base do |c|
16
+ # c.name = "filesystem"
17
+ # c.functional = true
18
+ # c.add_service(name: "my_file", path: "/var/www/my_project/my_file")
19
+ #
20
+ # c.on_error do |sevices|
21
+ # errors << "Custom error message for #{service[:name]}"
22
+ # end
23
+ #
24
+ # c.to_validate do |services, errors|
25
+ # services.each do |service|
26
+ # errors << "erro message" unless if File.exists?(service[:path])
27
+ # end
28
+ # end
29
+ # end
30
+
31
+ # Firewall
32
+ # check with telnet if the firewall is open to conect to the service
33
+ monitor.add :firewall do |c|
34
+ # you can add service wth (host and port) or (url)
35
+ c.add_service(host: 'lala.com', port: 80)
36
+ c.add_service(url: 'http://lalal.com')
37
+
38
+ # add dynamic services when you need it run after initializer
39
+ c.register_dynamic_services do
40
+ Pmta.all.map { |p| { host: p.host, port: 25 } }
41
+ end
42
+
43
+ # to customize default error message, the default is:
44
+ # "connection refused on: #{service.host}:#{service.port}"
45
+ # params
46
+ # errors: Array => errors to show on page
47
+ # service: FirewallService => object that respond to :host and :port
48
+ c.on_error do |_errors, service|
49
+ erros << "Custom error message for #{service.host}"
50
+ end
51
+ end
52
+
53
+ # Redis
54
+ # check if you redis conection is working
55
+ # you need to send a redis conection as a service
56
+ monitor.add :redis do |c|
57
+ c.add_service(name: 'Redis', connection: Resque.redis)
58
+ end
59
+
60
+ # Cache
61
+ # check if your cache is working
62
+ # you can pass any kind of cache, but this need to respond to
63
+ # set, get and delete
64
+ monitor.add :cache do |c|
65
+ c.add_service(name: 'memcached', connection: Rails.cache.instance_variable_get('@data'))
66
+ end
67
+ end
@@ -0,0 +1,111 @@
1
+ module Heartcheck
2
+ require 'logger'
3
+ require 'heartcheck/app'
4
+ require 'heartcheck/checks'
5
+ require 'heartcheck/errors'
6
+ require 'heartcheck/services'
7
+ require 'heartcheck/logger'
8
+
9
+ @checks = []
10
+
11
+ class << self
12
+ # @attr [Array<Checks>] the checks to use when checking
13
+ attr_accessor :checks
14
+ # @attr_writer [Object] change the default logger
15
+ attr_writer :logger
16
+
17
+ # Is used to log some messages when checking if the logger
18
+ # is not set it's returns de default_logger.
19
+ #
20
+ # @return [Object] the logger object
21
+ def logger
22
+ @logger ||= default_logger
23
+ end
24
+
25
+ # @abstract
26
+ # Is used to configure.
27
+ #
28
+ # @yield A bock that recieve the class
29
+ # @example
30
+ # Heartcheck.setup do |c|
31
+ # puts c
32
+ # end
33
+ # @return [void]
34
+ def setup
35
+ yield(self)
36
+ end
37
+
38
+ # It's used to add an instance of a check
39
+ # to the check list
40
+ #
41
+ # @param [String] name to identify in the result page
42
+ # @param [Hash] options the options to create an instance of a check.
43
+ # @option options [String] :class The class name to get an instance
44
+ # @yield a block to config the instance
45
+ # @example
46
+ # Heartcheck.add(:base) do |c|
47
+ # c.name = 'Base check'
48
+ # end
49
+ # @return [void]
50
+ def add(name, options = {}, &block)
51
+ class_name = options.fetch(:class) { constantize(name) }
52
+ instance = Checks.const_get(class_name).new
53
+
54
+ if block_given?
55
+ checks << instance.tap(&block)
56
+ else
57
+ checks << instance
58
+ end
59
+ end
60
+
61
+ # filter checks that are essential
62
+ #
63
+ # @return [Array<Check>] checks that are essential
64
+ def essential_checks
65
+ checks.select { |ctx| !ctx.functional? && !ctx.dev? }
66
+ end
67
+
68
+ # filter checks that are functional
69
+ #
70
+ # @return [Array<Check>] checks that are functional
71
+ def functional_checks
72
+ checks.select(&:functional?)
73
+ end
74
+
75
+ # filter checks that are not functional
76
+ #
77
+ # @return [Array<Check>] checks that are not functional
78
+ def dev_checks
79
+ checks.select { |ctx| !ctx.functional? }
80
+ end
81
+
82
+ # filter checks that has some information
83
+ #
84
+ # @return [Array<Check>] checks that respond to :info
85
+ def info_checks
86
+ checks.select { |ctx| ctx.respond_to?(:info) }
87
+ end
88
+
89
+ private
90
+
91
+ # if no logger is setted we create an instance
92
+ # of ruby logger with STDOUT
93
+ #
94
+ # @return [Logger] a ruby logger to STDOUT and info level
95
+ def default_logger
96
+ log = ::Logger.new(STDOUT)
97
+ log.level = ::Logger::INFO
98
+ log
99
+ end
100
+
101
+ # helper method to get a constant
102
+ #
103
+ # @example
104
+ # contantize('my_check') => 'MyCheck'
105
+ # @param [String] name of class
106
+ # @return [String]
107
+ def constantize(name)
108
+ name.to_s.split('_').map(&:capitalize).join
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,65 @@
1
+ require 'rack'
2
+ require 'heartcheck/controllers/base'
3
+
4
+ Dir.glob(File.expand_path('../controllers/*.rb', __FILE__))
5
+ .each { |x| require x }
6
+
7
+ # A web app that's use rack
8
+ module Heartcheck
9
+ class App
10
+ # A hash with paths as keys and controllers
11
+ # as values we use it in #dispath_action
12
+ # to routes the requests
13
+ ROUTE_TO_CONTROLLER = {
14
+ '/' => Controllers::Essential,
15
+ '' => Controllers::Essential,
16
+ '/functional' => Controllers::Functional,
17
+ '/dev' => Controllers::Dev,
18
+ '/info' => Controllers::Info,
19
+ '/health_check' => Controllers::HealthCheck
20
+ }
21
+
22
+ # Sets up the rack application.
23
+ #
24
+ # @param app [RackApp] is a rack app where
25
+ # heartcheck is included.
26
+ # @return [void]
27
+ def initialize(app = nil)
28
+ @app = app
29
+ end
30
+
31
+ # Sets up the rack application.
32
+ #
33
+ # @param env [Hash] is an instance of Hash
34
+ # that includes CGI-like headers.
35
+ # @return [Array] must be an array that contains
36
+ # - The HTTP response code
37
+ # - A Hash of headers
38
+ # - The response body, which must respond to each
39
+ def call(env)
40
+ req = Rack::Request.new(env)
41
+
42
+ [200, { 'Content-Type' => 'application/json' }, [dispatch_action(req)]]
43
+ rescue Heartcheck::Errors::RoutingError
44
+ [404, { 'Content-Type' => 'application/json' }, ['Not found']]
45
+ end
46
+
47
+ private
48
+
49
+ # Find a controller to espefic path
50
+ # and call the index method
51
+ #
52
+ # @param req [Rack::Request] an instance of request
53
+ # @return [String] a response body
54
+ def dispatch_action(req)
55
+ controller = ROUTE_TO_CONTROLLER[req.path_info]
56
+ fail Heartcheck::Errors::RoutingError if controller.nil?
57
+
58
+ Logger.info "Start [#{controller}] from #{req.ip} at #{Time.now}"
59
+
60
+ controller.new.index.tap do |_|
61
+ Logger.info "End [#{controller}]\n"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,3 @@
1
+ require 'heartcheck/checks/base'
2
+ require 'heartcheck/checks/firewall'
3
+ require 'heartcheck/checks/process'
@@ -0,0 +1,101 @@
1
+ module Heartcheck
2
+ module Checks
3
+ class Base
4
+ attr_accessor :functional, :dev, :name, :timeout
5
+
6
+ alias_method :functional?, :functional
7
+ alias_method :dev?, :dev
8
+
9
+ # call in Heartcheck.set
10
+ def initialize
11
+ @dynamic_services = nil
12
+ @error_proc = nil
13
+ @errors = []
14
+ @functional = false
15
+ @dev = false
16
+ @name = self.class.name.split('::').last.downcase
17
+ @services = []
18
+ @timeout = 0
19
+ @validate_proc = nil
20
+ end
21
+
22
+ def on_error(&block)
23
+ @error_proc = block if block_given?
24
+ end
25
+
26
+ def to_validate(&block)
27
+ @validate_proc = block if block_given?
28
+ end
29
+
30
+ def register_dynamic_services(&block)
31
+ @dynamic_services = block if block_given?
32
+ end
33
+
34
+ def add_service(service)
35
+ @services << service
36
+ end
37
+
38
+ def services
39
+ if @dynamic_services
40
+ @services + @dynamic_services.call
41
+ else
42
+ @services
43
+ end
44
+ end
45
+
46
+ def check
47
+ validation
48
+ hash = { name => { 'status' => (@errors.empty? ? 'ok' : 'error') } }
49
+ hash[name]['message'] = error_message unless @errors.empty?
50
+
51
+ Logger.info Oj.dump(hash)
52
+ hash
53
+ end
54
+
55
+ def informations
56
+ info
57
+ rescue => e
58
+ { 'error' => e.message }
59
+ end
60
+
61
+ private
62
+
63
+ def append_error(*args)
64
+ if @error_proc
65
+ @error_proc.call(@errors, *args)
66
+ else
67
+ custom_error(*args)
68
+ end
69
+ end
70
+
71
+ def validation
72
+ @errors = []
73
+ begin
74
+ Timeout.timeout(timeout, Heartcheck::Errors::Warning) do
75
+ if @validate_proc
76
+ @validate_proc.call(services, @errors)
77
+ else
78
+ validate
79
+ end
80
+ end
81
+ rescue Heartcheck::Errors::Warning => w
82
+ @errors = [{ type: 'warning', message: w.message }]
83
+ rescue => e
84
+ @errors = [e.message]
85
+ end
86
+ @errors
87
+ end
88
+
89
+ def error_message
90
+ @errors.map(&format_error)
91
+ end
92
+
93
+ def format_error
94
+ lambda do |error|
95
+ error.is_a?(Hash) ? error : { type: 'error', message: error }
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,26 @@
1
+ module Heartcheck
2
+ module Checks
3
+ class Firewall < Base
4
+ def services
5
+ super.map { |opts| Services::Firewall.new(opts) }
6
+ end
7
+
8
+ def validate
9
+ services.each do |service|
10
+ begin
11
+ Net::Telnet.new(service.params)
12
+ rescue Errno::ECONNREFUSED; nil
13
+ rescue
14
+ append_error(service)
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def custom_error(service)
22
+ @errors << "connection refused on: #{service.host}:#{service.port}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ module Heartcheck
2
+ module Checks
3
+ class Process < Base
4
+ def validate
5
+ services.each do |service|
6
+ begin
7
+ pid = get_pid(service)
8
+ ::Process.kill(0, pid)
9
+ rescue Errno::ESRCH
10
+ append_error(service, pid)
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def custom_error(service, pid)
18
+ @errors << "The process of #{service[:name]} is not run with pid #{pid}"
19
+ end
20
+
21
+ def get_pid(service)
22
+ if service[:pid]
23
+ service[:pid]
24
+ else
25
+ File.read(service[:file]).to_i
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'rack'
2
+ require 'oj'
3
+
4
+ Oj.default_options = { mode: :compat }
5
+
6
+ module Heartcheck
7
+ module Controllers
8
+ class Base
9
+ def index
10
+ fail NotImplementError
11
+ end
12
+
13
+ protected
14
+
15
+ def check(who)
16
+ Oj.dump(Heartcheck
17
+ .send("#{who}_checks")
18
+ .map(&:check))
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ module Heartcheck
2
+ module Controllers
3
+ class Dev < Base
4
+ def index
5
+ results = []
6
+
7
+ total_execution_time = time_diff do
8
+ checks = Heartcheck.dev_checks
9
+
10
+ results += checks.reduce([]) do |acc, elem|
11
+ context_result = {}
12
+
13
+ context_result['execution_time'] = time_diff do
14
+ context_result.merge!(elem.check)
15
+ end
16
+
17
+ acc << context_result
18
+ end
19
+ end
20
+
21
+ results << { 'total_execution_time' => total_execution_time }
22
+ Oj.dump(results)
23
+ end
24
+
25
+ private
26
+
27
+ def time_diff
28
+ start_time = Time.now
29
+ yield
30
+ '%.2f ms' % ((Time.now - start_time) * 1_000)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module Heartcheck
2
+ module Controllers
3
+ class Essential < Base
4
+ def index
5
+ check(:essential)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Heartcheck
2
+ module Controllers
3
+ class Functional < Base
4
+ def index
5
+ check(:functional)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Heartcheck
2
+ module Controllers
3
+ class HealthCheck < Base
4
+ def index
5
+ Oj.dump({ status: 'ok' })
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Heartcheck
2
+ module Controllers
3
+ class Info < Base
4
+ def index
5
+ Oj.dump(Heartcheck
6
+ .info_checks
7
+ .map(&:informations))
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ require 'heartcheck/errors/routing_error'
2
+ require 'heartcheck/errors/warning'
@@ -0,0 +1,6 @@
1
+ module Heartcheck
2
+ module Errors
3
+ class RoutingError < RuntimeError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Heartcheck
2
+ module Errors
3
+ class Warning < RuntimeError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,53 @@
1
+ module Heartcheck
2
+ # A simple Interface to log messages
3
+ class Logger
4
+ # log message with debug level
5
+ #
6
+ # @param message [String] message to log
7
+ # @return [void]
8
+ def self.debug(message)
9
+ logger(:debug, message)
10
+ end
11
+
12
+ # log message with info level
13
+ #
14
+ # @param message [String] message to log
15
+ #
16
+ # @return [void]
17
+ def self.info(message)
18
+ logger(:info, message)
19
+ end
20
+
21
+ # log message with warn level
22
+ #
23
+ # @param message [String] message to log
24
+ #
25
+ # @return [void]
26
+ def self.warn(message)
27
+ logger(:warn, message)
28
+ end
29
+
30
+ # log message with error level
31
+ #
32
+ # @param message [String] message to log
33
+ #
34
+ # @return [void]
35
+ def self.error(message)
36
+ logger(:error, message)
37
+ end
38
+
39
+ private
40
+
41
+ # Sent the message to Heartcheck logger
42
+ # that you can configure
43
+ #
44
+ # @see Heartcheck.logger
45
+ # @param level [Symbol] the level log
46
+ # @param message [String] message to log
47
+ #
48
+ # @return [void]
49
+ def self.logger(level, message)
50
+ Heartcheck.logger.send(level, "[Heartcheck] #{message}")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1 @@
1
+ require 'heartcheck/services/firewall'
@@ -0,0 +1,72 @@
1
+ require 'net/telnet'
2
+
3
+ module Heartcheck
4
+ module Services
5
+ # A service to check with a simple telnet
6
+ # if the route to a host is working.
7
+ class Firewall
8
+ attr_reader :uri, :proxy
9
+
10
+ # Sets up the options to firewall.
11
+ #
12
+ # @param params [Hash] a hash with the configurations.
13
+ # @option params [String] :host The domain/Ip
14
+ # @option params [Integer] :port Number of port to check
15
+ # @option params [String] :proxy The uri of your proxy if is required
16
+ # @option params [integer] :timeout (defaults to: 2) Number in seconds
17
+ # @option params [string] :uri You can pass a URI instead a host and port
18
+ #
19
+ # @example
20
+ # Firewall.new(host: 'domain.com', port: 80)
21
+ # Firewall.new(host: 'domain.com', port: 80, timeout: 5)
22
+ # Firewall.new(uri: 'https://domain.com')
23
+ # Firewall.new(uri: 'https://domain.com', proxy: 'http://proxy.domain.com')
24
+ #
25
+ # @return [void]
26
+ def initialize(params)
27
+ @host = params[:host]
28
+ @port = params[:port]
29
+ @proxy = params[:proxy]
30
+ @timeout = params[:timeout] || 2
31
+ @uri = URI(params[:url].to_s)
32
+ end
33
+
34
+ # format params to use in Telnet
35
+ #
36
+ # @return [Hash] with the config
37
+ # - Host
38
+ # - Port
39
+ # - Timeout
40
+ # - Proxy - if is seted return a Net::Telnet object
41
+ def params
42
+ params = { 'Host' => host, 'Port' => port, 'Timeout' => @timeout }
43
+ params['Proxy'] = proxy_uri if proxy
44
+ params
45
+ end
46
+
47
+ # to get the host or stract from @uri
48
+ #
49
+ # @return [String] the host that is configured
50
+ def host
51
+ @host || uri.host
52
+ end
53
+
54
+ # to get the port or stract from @uri
55
+ #
56
+ # @return [Integre] the port that is configured
57
+ def port
58
+ @port || uri.port
59
+ end
60
+
61
+ private
62
+
63
+ # to get the configured proxy
64
+ #
65
+ # @return [Net::Telnet] an instance with configured proxy
66
+ def proxy_uri
67
+ uri_proxy = URI(proxy)
68
+ ::Net::Telnet.new('Host' => uri_proxy.host, 'Port' => uri_proxy.port, 'Timeout' => @timeout)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module Heartcheck
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,248 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heartcheck
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Locaweb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.0
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.6.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.0
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.6.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: oj
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.11.0
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.11.4
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 2.11.0
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.11.4
53
+ - !ruby/object:Gem::Dependency
54
+ name: pry-nav
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: 0.2.0
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.2.4
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 0.2.0
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 0.2.4
73
+ - !ruby/object:Gem::Dependency
74
+ name: rspec
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 3.1.0
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.1.0
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.1.0
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 3.1.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: rubocop
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: 0.27.0
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.27.1
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 0.27.0
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 0.27.1
113
+ - !ruby/object:Gem::Dependency
114
+ name: thor
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: 0.19.0
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 0.19.1
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: 0.19.0
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 0.19.1
133
+ - !ruby/object:Gem::Dependency
134
+ name: rack-test
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: 0.6.0
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 0.6.3
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: 0.6.0
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 0.6.3
153
+ - !ruby/object:Gem::Dependency
154
+ name: yard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.8.0
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 0.8.7
163
+ type: :development
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: 0.8.0
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 0.8.7
173
+ - !ruby/object:Gem::Dependency
174
+ name: redcarpet
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: 3.2.0
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: 3.2.2
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: 3.2.0
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 3.2.2
193
+ description: A simple way to check your app heart.
194
+ email:
195
+ - desenvolvedores@locaweb.com.br
196
+ executables:
197
+ - heartcheck
198
+ extensions: []
199
+ extra_rdoc_files: []
200
+ files:
201
+ - bin/heartcheck
202
+ - lib/generators/generator.rb
203
+ - lib/generators/templates/config.rb
204
+ - lib/heartcheck.rb
205
+ - lib/heartcheck/app.rb
206
+ - lib/heartcheck/checks.rb
207
+ - lib/heartcheck/checks/base.rb
208
+ - lib/heartcheck/checks/firewall.rb
209
+ - lib/heartcheck/checks/process.rb
210
+ - lib/heartcheck/controllers/base.rb
211
+ - lib/heartcheck/controllers/dev.rb
212
+ - lib/heartcheck/controllers/essential.rb
213
+ - lib/heartcheck/controllers/functional.rb
214
+ - lib/heartcheck/controllers/health_check.rb
215
+ - lib/heartcheck/controllers/info.rb
216
+ - lib/heartcheck/errors.rb
217
+ - lib/heartcheck/errors/routing_error.rb
218
+ - lib/heartcheck/errors/warning.rb
219
+ - lib/heartcheck/logger.rb
220
+ - lib/heartcheck/services.rb
221
+ - lib/heartcheck/services/firewall.rb
222
+ - lib/heartcheck/version.rb
223
+ homepage: http://developer.locaweb.com.br
224
+ licenses:
225
+ - MIT
226
+ metadata: {}
227
+ post_install_message:
228
+ rdoc_options: []
229
+ require_paths:
230
+ - lib
231
+ required_ruby_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ required_rubygems_version: !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - ">="
239
+ - !ruby/object:Gem::Version
240
+ version: '0'
241
+ requirements: []
242
+ rubyforge_project:
243
+ rubygems_version: 2.4.5
244
+ signing_key:
245
+ specification_version: 4
246
+ summary: A simple way to check if your app is runnig like as expected.
247
+ test_files: []
248
+ has_rdoc: