rt_health_monitor 0.8.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/Changelog.md +19 -0
- data/Gemfile +4 -0
- data/README.md +121 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/health_monitor.rb +6 -0
- data/lib/health_monitor/middleware/health_monitor_middleware.rb +48 -0
- data/lib/health_monitor/monitors/health_monitor.rb +55 -0
- data/lib/health_monitor/monitors/service_health_monitor.rb +32 -0
- data/lib/health_monitor/monitors/simple_health_monitor.rb +33 -0
- data/lib/health_monitor/rake_task.rb +27 -0
- data/lib/health_monitor/version.rb +3 -0
- data/rt_health_monitor.gemspec +27 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13cb464b9e81668abf4c5dc72a0f48c6e1834e0ebb4e19dcbe51a73ee5a1cb5e
|
4
|
+
data.tar.gz: 66d0c9256a656bbf89ffa4abb59ba4bb5ee81cb38be3281effc4899fb44bac3b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f26b2584e91dfd22b718412fcbbb7d970e074e78b844cd494628b0f0a322f308297840440aac31fbc1cbea32a89598a5023e063722d8d3a0a46dd987188d2b4
|
7
|
+
data.tar.gz: '092792193524f8f4f553299cbed038f4371daf1bba63ec6d42d4d2ec807891aa6e2bdcf9152c69e41b15c813f5024ef020efc77886584d05ac65e405b282af80'
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Changelog.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
Purpose
|
2
|
+
=======
|
3
|
+
|
4
|
+
* Get information about your applications health status easily
|
5
|
+
|
6
|
+
Usage
|
7
|
+
=====
|
8
|
+
|
9
|
+
Add the gem to your Gemfile
|
10
|
+
|
11
|
+
gem 'rt_health_monitor', require: 'health_monitor'
|
12
|
+
|
13
|
+
Add the middleware to your config.
|
14
|
+
|
15
|
+
### Rails
|
16
|
+
|
17
|
+
Add to you Rails configuration (config/application.rb)
|
18
|
+
|
19
|
+
module <ApplicationName>
|
20
|
+
class Application < Rails::Application
|
21
|
+
config.middleware.use ::HealthMonitorMiddleware, "your_application_name"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
### Sinatra
|
26
|
+
|
27
|
+
Add to config.ru
|
28
|
+
|
29
|
+
use HealthMonitorMiddleware, "your_application_name"
|
30
|
+
|
31
|
+
### Padrino
|
32
|
+
|
33
|
+
Add to config/apps.rb
|
34
|
+
|
35
|
+
Padrino.use(HealthMonitorMiddleware, "your_application_name")
|
36
|
+
|
37
|
+
|
38
|
+
## Configure your dependencies
|
39
|
+
|
40
|
+
Put into some place which is loaded on startup, like config/initializer/health_monitor_initializer.rb
|
41
|
+
|
42
|
+
HealthMonitorMiddleware.add("simple", name: "MySQL") { User.where{id > 0}.limit(1) }
|
43
|
+
|
44
|
+
HealthMonitorMiddleware.add("service", name: 'some_service_name') { RestClient.get(File.join(service-url, 'healthmonitor')) }
|
45
|
+
|
46
|
+
Simple-Monitor needs some block which returns true or false for up an down state. Service-Monitor needs an block which returns a complete status response in JSON format. This may be just the health-monitor used by a service.
|
47
|
+
|
48
|
+
## Outcome
|
49
|
+
|
50
|
+
As soon as the middleware is configured and your application is running, you can acess the health monitor status page adding 'healthmonitor' to your url. It does not depend on the given path.
|
51
|
+
|
52
|
+
http://your_application_url_with_some_path/healthmonitor
|
53
|
+
|
54
|
+
This would lead to the following output f.e.:
|
55
|
+
|
56
|
+
{
|
57
|
+
status: "down",
|
58
|
+
name: "my app",
|
59
|
+
simple: [
|
60
|
+
{
|
61
|
+
status: "up",
|
62
|
+
name: "MySQL",
|
63
|
+
time: 0.2758502960205078
|
64
|
+
},
|
65
|
+
{
|
66
|
+
status: "up",
|
67
|
+
name: "Memcached",
|
68
|
+
time: 1.4078617095947266
|
69
|
+
},
|
70
|
+
{
|
71
|
+
status: "up",
|
72
|
+
name: "Resque",
|
73
|
+
time: 3.2737255096435547
|
74
|
+
}
|
75
|
+
],
|
76
|
+
service: [
|
77
|
+
{
|
78
|
+
status: "down",
|
79
|
+
name: "routes",
|
80
|
+
time: 1295.3431606292725
|
81
|
+
},
|
82
|
+
{
|
83
|
+
status: "up",
|
84
|
+
name: "appendix",
|
85
|
+
info: {
|
86
|
+
simple: [
|
87
|
+
{
|
88
|
+
status: "up",
|
89
|
+
name: "MongoDB",
|
90
|
+
time: 6.000041961669922
|
91
|
+
},
|
92
|
+
{
|
93
|
+
status: "up",
|
94
|
+
name: "MySQL",
|
95
|
+
time: 0
|
96
|
+
}
|
97
|
+
]
|
98
|
+
},
|
99
|
+
time: 23.989439010620117
|
100
|
+
},
|
101
|
+
...
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
## Sidekiq Health Check Task
|
106
|
+
|
107
|
+
A task for performing a Sidekiq health check is also included. To use that, just add the following line to your `Rakefile`
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
require "health_monitor/rake_task"
|
111
|
+
```
|
112
|
+
|
113
|
+
You must have a `environment` task in your `Rakefile` which loads the environment. Rails already provides such a task.
|
114
|
+
|
115
|
+
A simple environment task looks like this:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
task :environment do
|
119
|
+
require_relative "./config/environment" if File.exists?("./config/environment")
|
120
|
+
end
|
121
|
+
```
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "health_monitor"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'health_monitor/monitors/health_monitor'
|
3
|
+
require 'health_monitor/monitors/simple_health_monitor'
|
4
|
+
require 'health_monitor/monitors/service_health_monitor'
|
5
|
+
require 'health_monitor/middleware/health_monitor_middleware'
|
6
|
+
require 'health_monitor/version'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class HealthMonitorMiddleware
|
5
|
+
|
6
|
+
@@monitor = HealthMonitor.new(name: nil)
|
7
|
+
|
8
|
+
def initialize(app, name, uri = nil)
|
9
|
+
@app = app
|
10
|
+
@uri = uri || "health_monitor"
|
11
|
+
@@monitor.name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
return @app.call(env) unless env["REQUEST_URI"] =~ /#{@uri}/
|
16
|
+
request = Rack::Request.new(env)
|
17
|
+
|
18
|
+
stime = Time.now
|
19
|
+
data = @@monitor.get_status(request.params)
|
20
|
+
data[:time] = (Time.now - stime)
|
21
|
+
|
22
|
+
make_response(env, data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.add(type, params, &block)
|
26
|
+
@@monitor.send("add_#{type}", params, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private def response_code(data)
|
30
|
+
return 503 unless data[:status] == :up
|
31
|
+
200
|
32
|
+
end
|
33
|
+
|
34
|
+
private def xml_response(data)
|
35
|
+
status = (data[:status] == :up) ? 'OK' : 'FAILED'
|
36
|
+
'<pingdom_http_custom_check>' \
|
37
|
+
"<status>#{status}</status>" \
|
38
|
+
"<response_time>#{data[:time].round(3)}</response_time>" \
|
39
|
+
'</pingdom_http_custom_check>'
|
40
|
+
end
|
41
|
+
|
42
|
+
private def make_response(env, data)
|
43
|
+
if env['REQUEST_URI'] =~ /pingdom/
|
44
|
+
return [response_code(data), { 'Content-Type' => 'application/xml' }, [xml_response(data)]]
|
45
|
+
end
|
46
|
+
[response_code(data), { 'Content-Type' => 'application/json' }, [data.to_json]]
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class HealthMonitor
|
2
|
+
|
3
|
+
attr_accessor :name, :config, :status, :info, :time
|
4
|
+
|
5
|
+
def initialize(params = {})
|
6
|
+
params.each do |k,v|
|
7
|
+
self.send("#{k}=",v) if self.respond_to?("#{k}=")
|
8
|
+
end
|
9
|
+
@targets ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_status(params = {})
|
13
|
+
self.status = :up
|
14
|
+
|
15
|
+
check = params["check"].try(:split,',') || @targets.map(&:name)
|
16
|
+
check = check.map{ |t| t.downcase }
|
17
|
+
|
18
|
+
dont_check = params["dont_check"].try(:split,',') || []
|
19
|
+
dont_check = dont_check.map{ |t| t.downcase }
|
20
|
+
|
21
|
+
result = { status: status, name: name }
|
22
|
+
result[:time] = time if time
|
23
|
+
result[:info] = info.slice("simple","service") if info
|
24
|
+
|
25
|
+
(@targets || []).each do |target|
|
26
|
+
|
27
|
+
next unless check.include?(target.name.downcase)
|
28
|
+
next if dont_check.include?(target.name.downcase)
|
29
|
+
|
30
|
+
res = target.get_status
|
31
|
+
|
32
|
+
result[target.type] ||= []
|
33
|
+
result[target.type] << res
|
34
|
+
|
35
|
+
result[:status] = :down if res[:status].to_sym == :down
|
36
|
+
end
|
37
|
+
|
38
|
+
self.status = result[:status]
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_target(target)
|
44
|
+
@targets << target
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_simple(opts, &block)
|
48
|
+
add_target(SimpleHealthMonitor.new(opts, &block))
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_service(opts, &block)
|
52
|
+
add_target(ServiceHealthMonitor.new(opts, &block))
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class ServiceHealthMonitor < HealthMonitor
|
2
|
+
def type
|
3
|
+
:service
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(params = {}, &block)
|
7
|
+
params.each do |k,v|
|
8
|
+
self.send("#{k}=",v) if self.respond_to?("#{k}=")
|
9
|
+
end
|
10
|
+
|
11
|
+
@block = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_status
|
15
|
+
self.info = nil
|
16
|
+
|
17
|
+
begin
|
18
|
+
self.time = Benchmark.measure do
|
19
|
+
self.info = JSON.parse(@block.call) if @block
|
20
|
+
end.real * 1000
|
21
|
+
self.status = self.info["status"]
|
22
|
+
rescue
|
23
|
+
self.status = :down
|
24
|
+
end
|
25
|
+
|
26
|
+
result = { status: status, name: name }
|
27
|
+
result[:info] = info.slice("simple","service") if info
|
28
|
+
result[:time] = time if time
|
29
|
+
|
30
|
+
result
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class SimpleHealthMonitor < HealthMonitor
|
2
|
+
def type
|
3
|
+
:simple
|
4
|
+
end
|
5
|
+
|
6
|
+
def info
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(params = {}, &block)
|
10
|
+
params.each do |k,v|
|
11
|
+
self.send("#{k}=",v) if self.respond_to?("#{k}=")
|
12
|
+
end
|
13
|
+
|
14
|
+
@block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_status
|
18
|
+
begin
|
19
|
+
self.time = Benchmark.measure do
|
20
|
+
self.status = !!@block.call if @block
|
21
|
+
end.real * 1000
|
22
|
+
rescue
|
23
|
+
self.status = false
|
24
|
+
end
|
25
|
+
|
26
|
+
self.status = (self.status ? :up : :down)
|
27
|
+
|
28
|
+
result = { status: status, name: name }
|
29
|
+
result[:time] = time if time
|
30
|
+
|
31
|
+
result
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
|
5
|
+
class RakeTask
|
6
|
+
include Rake::DSL if defined? Rake::DSL
|
7
|
+
|
8
|
+
def install_tasks
|
9
|
+
desc "Check if Sidekiq is running"
|
10
|
+
task "health_monitor:sidekiq:health" => :environment do
|
11
|
+
require "sidekiq/api"
|
12
|
+
hostname = ENV["HOSTNAME"] || `hostname -f`.strip
|
13
|
+
ps = ::Sidekiq::ProcessSet.new
|
14
|
+
up = ps.any? { |p| p["hostname"] == hostname && p["quiet"] == "false" }
|
15
|
+
|
16
|
+
if up
|
17
|
+
puts "UP"
|
18
|
+
exit 0
|
19
|
+
end
|
20
|
+
|
21
|
+
puts "DOWN"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RakeTask.new.install_tasks
|
@@ -0,0 +1,27 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "health_monitor/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rt_health_monitor"
|
7
|
+
spec.version = HealthMonitor::VERSION
|
8
|
+
spec.authors = ["Martin Fuehrlinger", "0xdco", "Georg Gadinger"]
|
9
|
+
spec.email = ["maf@runtastic.com", "wv@0xd.co", "nilsding@nilsding.org"]
|
10
|
+
|
11
|
+
spec.summary = "Monitor your db and services health!"
|
12
|
+
spec.description = "Monitoring"
|
13
|
+
spec.homepage = "https://github.com/runtastic/health_monitor"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "rack"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rt_health_monitor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0.pre.rc1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Martin Fuehrlinger
|
8
|
+
- 0xdco
|
9
|
+
- Georg Gadinger
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2018-04-16 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: bundler
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rake
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rspec
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
description: Monitoring
|
72
|
+
email:
|
73
|
+
- maf@runtastic.com
|
74
|
+
- wv@0xd.co
|
75
|
+
- nilsding@nilsding.org
|
76
|
+
executables: []
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- ".gitignore"
|
81
|
+
- ".rspec"
|
82
|
+
- Changelog.md
|
83
|
+
- Gemfile
|
84
|
+
- README.md
|
85
|
+
- Rakefile
|
86
|
+
- bin/console
|
87
|
+
- bin/setup
|
88
|
+
- lib/health_monitor.rb
|
89
|
+
- lib/health_monitor/middleware/health_monitor_middleware.rb
|
90
|
+
- lib/health_monitor/monitors/health_monitor.rb
|
91
|
+
- lib/health_monitor/monitors/service_health_monitor.rb
|
92
|
+
- lib/health_monitor/monitors/simple_health_monitor.rb
|
93
|
+
- lib/health_monitor/rake_task.rb
|
94
|
+
- lib/health_monitor/version.rb
|
95
|
+
- rt_health_monitor.gemspec
|
96
|
+
homepage: https://github.com/runtastic/health_monitor
|
97
|
+
licenses: []
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 1.3.1
|
113
|
+
requirements: []
|
114
|
+
rubyforge_project:
|
115
|
+
rubygems_version: 2.7.3
|
116
|
+
signing_key:
|
117
|
+
specification_version: 4
|
118
|
+
summary: Monitor your db and services health!
|
119
|
+
test_files: []
|