kingkong 0.0.3 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -14
- data/README.md +30 -11
- data/kingkong.gemspec +10 -3
- data/lib/kingkong.rb +6 -2
- data/lib/kingkong/pinger.rb +18 -7
- data/lib/kingkong/runner.rb +32 -11
- data/lib/kingkong/version.rb +1 -1
- data/spec/lib/kingkong/pinger_spec.rb +24 -24
- data/spec/lib/kingkong/runner_spec.rb +11 -4
- data/spec/spec_helper.rb +26 -0
- metadata +93 -12
- data/lib/kingkong/aggregator.rb +0 -71
- data/lib/kingkong/reporting.rb +0 -37
- data/lib/kingkong/server.rb +0 -24
- data/spec/lib/kingkong/aggregator_spec.rb +0 -32
data/Gemfile
CHANGED
@@ -1,17 +1,4 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in kingkong.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem 'em-http-request'
|
7
|
-
gem 'json'
|
8
|
-
|
9
|
-
group :test, :development do
|
10
|
-
gem 'rspec'
|
11
|
-
gem 'guard-rspec'
|
12
|
-
gem 'growl'
|
13
|
-
gem 'rb-fsevent'
|
14
|
-
gem 'em-ventually'
|
15
|
-
gem 'timecop'
|
16
|
-
gem 'ruby-debug19'
|
17
|
-
end
|
4
|
+
gemspec
|
data/README.md
CHANGED
@@ -30,27 +30,46 @@
|
|
30
30
|
|
31
31
|
KingKong makes it easy to build full-stack ping-pong health checks so you can keep an eye on crucial input/outputs and make sure things stay nice and fast. You might need this to check and graph out the response time on your website, Twitter application, SMS gateway, or whatever else you'd connect to a network.
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
## Getting Started
|
34
|
+
|
35
|
+
Install the KingKong gem.
|
36
|
+
|
37
|
+
gem install kingkong
|
38
|
+
|
39
|
+
Then implement your ping checks in Ruby.
|
40
|
+
|
35
41
|
require 'kingkong'
|
36
42
|
require 'em-http-request'
|
37
|
-
|
38
|
-
|
43
|
+
|
44
|
+
KingKong.start {
|
39
45
|
socket '/tmp/king_kong.socket' # Check this socket with Munin and make a graph!
|
40
|
-
|
46
|
+
|
41
47
|
ping(:google).every(3).seconds do |ping|
|
42
|
-
|
48
|
+
ping.start
|
49
|
+
google = EventMachine::HttpRequest.new('http://google.com/').get
|
43
50
|
google.callback { ping.stop }
|
44
|
-
google.errback
|
45
|
-
ping.start and google.get
|
51
|
+
google.errback { ping.fail }
|
46
52
|
end
|
47
|
-
|
53
|
+
|
48
54
|
ping(:twitter).every(10).seconds do |ping|
|
49
55
|
# Wire up your own thing in here that tweets
|
50
56
|
# .. and when you pick that up, end the pong!
|
51
57
|
end
|
58
|
+
|
59
|
+
ping(:verizon).every(2).seconds do |ping|
|
60
|
+
# Hook your machine up to a GSM serial modem
|
61
|
+
# and perform regular SMS pings against your app.
|
62
|
+
end
|
52
63
|
}
|
53
64
|
|
54
|
-
|
65
|
+
Save the file and run it! You'll see some crazy log output right now, but eventually its going to be prettier.
|
66
|
+
|
67
|
+
You can see the stat aggregates of the pings by looking into the socket:
|
68
|
+
|
69
|
+
watch cat /tmp/king_kong.socket
|
70
|
+
|
71
|
+
If you don't understand EventMachine, you might have a little trouble getting this stuff working. Eventually I'd like to hook up Em::Syncrony and a nicer DSL for common tasks, like HTTP checks, to keep things simple.
|
72
|
+
|
73
|
+
## Using KingKong with Munin graphs
|
55
74
|
|
56
|
-
|
75
|
+
I'm working on this!
|
data/kingkong.gemspec
CHANGED
@@ -18,7 +18,14 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'guard-rspec'
|
23
|
+
s.add_development_dependency 'growl'
|
24
|
+
s.add_development_dependency 'rb-fsevent'
|
25
|
+
s.add_development_dependency 'em-ventually'
|
26
|
+
s.add_development_dependency 'timecop'
|
27
|
+
s.add_development_dependency 'ruby-debug19'
|
28
|
+
|
23
29
|
s.add_runtime_dependency "eventmachine"
|
24
|
-
|
30
|
+
s.add_runtime_dependency "nosey"
|
31
|
+
end
|
data/lib/kingkong.rb
CHANGED
@@ -4,17 +4,21 @@ module KingKong
|
|
4
4
|
autoload :Ping, 'kingkong/ping'
|
5
5
|
autoload :Pinger, 'kingkong/pinger'
|
6
6
|
autoload :Runner, 'kingkong/runner'
|
7
|
-
autoload :Server, 'kingkong/server'
|
8
7
|
autoload :Logging, 'kingkong/logging'
|
9
8
|
autoload :Aggregator, 'kingkong/aggregator'
|
10
|
-
autoload :Reporting, 'kingkong/reporting'
|
11
9
|
|
12
10
|
# Default logger for KingKong.
|
13
11
|
def self.logger
|
14
12
|
@logger ||= Logger.new($stdout)
|
15
13
|
end
|
16
14
|
|
15
|
+
# Want to override the default logger? Its cool, change it up here.
|
17
16
|
def self.logger=(logger)
|
18
17
|
@logger = logger
|
19
18
|
end
|
19
|
+
|
20
|
+
# Shortcut for starting a runner
|
21
|
+
def self.start(*args)
|
22
|
+
Runner.new(*args)
|
23
|
+
end
|
20
24
|
end
|
data/lib/kingkong/pinger.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
+
require 'nosey'
|
2
3
|
|
3
4
|
module KingKong
|
4
5
|
class Pinger
|
5
6
|
include Logging
|
7
|
+
include Nosey::Instrumentation
|
6
8
|
|
7
9
|
attr_reader :wait
|
8
10
|
|
@@ -25,11 +27,6 @@ module KingKong
|
|
25
27
|
@timer.cancel if @timer
|
26
28
|
end
|
27
29
|
|
28
|
-
# Gather up all the numbers we need for reporting later on
|
29
|
-
def aggregator
|
30
|
-
@aggregatore ||= Aggregator.new
|
31
|
-
end
|
32
|
-
|
33
30
|
private
|
34
31
|
# Add all of the instrumentation callbacks into the ping so we can aggregate it later
|
35
32
|
def ping
|
@@ -38,12 +35,12 @@ module KingKong
|
|
38
35
|
# Register the aggregator to process the ping
|
39
36
|
ping.callback {
|
40
37
|
logger.debug "Ping #{ping} successful"
|
41
|
-
|
38
|
+
process ping
|
42
39
|
}
|
43
40
|
|
44
41
|
ping.errback {
|
45
42
|
logger.debug "Ping #{ping} error (probably a timeout)"
|
46
|
-
|
43
|
+
process ping
|
47
44
|
}
|
48
45
|
|
49
46
|
# Now pass the ping into the block so we can start/stop it
|
@@ -54,5 +51,19 @@ module KingKong
|
|
54
51
|
def sequencer
|
55
52
|
@sequencer ||= Ping::Sequencer.new
|
56
53
|
end
|
54
|
+
|
55
|
+
# Process a stinkin ping and report aggregate stats to Nosey
|
56
|
+
def process(ping)
|
57
|
+
nosey.increment 'ping_count'
|
58
|
+
case ping.status
|
59
|
+
when :timed_out
|
60
|
+
nosey.increment 'ping_timed_out_count'
|
61
|
+
when :completed
|
62
|
+
nosey.increment 'ping_completed_count'
|
63
|
+
nosey.avg "ping_avg_latency", ping.latency
|
64
|
+
nosey.min "ping_min_latency", ping.latency
|
65
|
+
nosey.max "ping_max_latency", ping.latency
|
66
|
+
end
|
67
|
+
end
|
57
68
|
end
|
58
69
|
end
|
data/lib/kingkong/runner.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
|
+
require 'nosey'
|
2
|
+
|
1
3
|
module KingKong
|
2
4
|
# Configure multiple pingers to run
|
3
5
|
class Runner
|
4
6
|
include Logging
|
5
7
|
|
6
8
|
# Array of pingers that we're running
|
7
|
-
def ping(name)
|
8
|
-
|
9
|
+
def ping(name, &block)
|
10
|
+
DSL::Pinger.new(&block).completed do |pinger|
|
11
|
+
pinger.nosey.name = name.to_s
|
12
|
+
pingers << pinger
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
16
|
# Setup the socket that this thing will write stats out to
|
12
|
-
def socket(host=
|
17
|
+
def socket(host='/tmp/king_kong.socket', port=nil)
|
13
18
|
@socket_host , @socket_port = host, port
|
14
19
|
end
|
15
20
|
|
@@ -47,7 +52,14 @@ module KingKong
|
|
47
52
|
private
|
48
53
|
# Fire up the reporting server if a socket (and port, optionally) are given
|
49
54
|
def start_socket
|
50
|
-
|
55
|
+
EM::Nosey::SocketServer.start(nosey_report, @socket_host, @socket_port) if @socket_host
|
56
|
+
end
|
57
|
+
|
58
|
+
# Get us the nosey report that our nosey socket needs to get the job done son!
|
59
|
+
def nosey_report
|
60
|
+
Nosey::Report.new do |r|
|
61
|
+
r.probe_sets = pingers.map(&:nosey)
|
62
|
+
end
|
51
63
|
end
|
52
64
|
|
53
65
|
# Fire up all the pingers
|
@@ -55,15 +67,9 @@ module KingKong
|
|
55
67
|
pingers.each(&:start)
|
56
68
|
end
|
57
69
|
|
58
|
-
# Hang onto pinger configuration so that we can configure pinger instances and fire them
|
59
|
-
# off. We'll also be using this for writing reports.
|
60
|
-
def pinger_configurations
|
61
|
-
@pinger_configurations ||= Hash.new{|hash,val| hash[val] = DSL::Pinger.new }
|
62
|
-
end
|
63
|
-
|
64
70
|
# Create instances of pingers from the configurations that we setup in the runner
|
65
71
|
def pingers
|
66
|
-
@pingers ||=
|
72
|
+
@pingers ||= []
|
67
73
|
end
|
68
74
|
|
69
75
|
def self.ensure_running_reactor(&block)
|
@@ -92,18 +98,21 @@ module KingKong
|
|
92
98
|
# Configure duration as seconds
|
93
99
|
def seconds(&block)
|
94
100
|
unitize Unit::Second, &block
|
101
|
+
complete
|
95
102
|
end
|
96
103
|
alias :second :seconds
|
97
104
|
|
98
105
|
# Configure the duration as minutes
|
99
106
|
def minutes(&block)
|
100
107
|
unitize Unit::Minute, &block
|
108
|
+
complete
|
101
109
|
end
|
102
110
|
alias :minute :minutes
|
103
111
|
|
104
112
|
# Configure the ping duration as hours
|
105
113
|
def hours(&block)
|
106
114
|
unitize Unit::Hour, &block
|
115
|
+
complete
|
107
116
|
end
|
108
117
|
alias :hour :hours
|
109
118
|
|
@@ -117,6 +126,12 @@ module KingKong
|
|
117
126
|
KingKong::Pinger.new(duration, &@block)
|
118
127
|
end
|
119
128
|
|
129
|
+
# Callback when we've completed the configuration of this thing.
|
130
|
+
def completed(&block)
|
131
|
+
@completed_blk = block
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
120
135
|
private
|
121
136
|
# Figures out the number of seconds that we multply by the units
|
122
137
|
def unitize(units, &block)
|
@@ -124,6 +139,12 @@ module KingKong
|
|
124
139
|
@block = block
|
125
140
|
self
|
126
141
|
end
|
142
|
+
|
143
|
+
# Yay! Its complete!
|
144
|
+
def complete
|
145
|
+
@completed_blk.call(pinger) if @completed_blk
|
146
|
+
self
|
147
|
+
end
|
127
148
|
end
|
128
149
|
end
|
129
150
|
end
|
data/lib/kingkong/version.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
require 'spec_helper'
|
1
|
+
# require 'spec_helper'
|
2
2
|
|
3
|
-
describe KingKong::Pinger do
|
4
|
-
|
3
|
+
# describe KingKong::Pinger do
|
4
|
+
# include EM::Ventually
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
# before(:all) do
|
7
|
+
# @@pinged = false
|
8
|
+
# @pinger = KingKong::Pinger.new(0.1) do |ping, pinger|
|
9
|
+
# @@ping = ping
|
10
|
+
# ping.start
|
11
|
+
# ping.stop
|
12
|
+
# pinger.stop
|
13
|
+
# end
|
14
|
+
# end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
# it "should ping" do
|
17
|
+
# @pinger.start
|
18
|
+
# ly(:completed) { @@ping.status }
|
19
|
+
# end
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
# it "should stop"
|
22
|
+
# it "should start"
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
24
|
+
# context "ping aggregation" do
|
25
|
+
# it "should process timed-out"
|
26
|
+
# it "should process successful"
|
27
|
+
# it "should process errors"
|
28
|
+
# end
|
29
|
+
# end
|
@@ -8,13 +8,17 @@ describe KingKong::Runner do
|
|
8
8
|
@@google_pinged = @@twitter_pinged = false
|
9
9
|
|
10
10
|
@runner = KingKong::Runner.configure do |runner|
|
11
|
-
runner.socket '/tmp/
|
11
|
+
runner.socket '/tmp/king_kong_test.socket'
|
12
12
|
|
13
|
-
runner.ping(:google).every(0.1).seconds do
|
13
|
+
runner.ping(:google).every(0.1).seconds do |ping|
|
14
|
+
ping.start
|
15
|
+
ping.stop
|
14
16
|
@@google_pinged = true
|
15
17
|
end
|
16
18
|
|
17
|
-
runner.ping(:twitter).every(2).seconds do
|
19
|
+
runner.ping(:twitter).every(2).seconds do |ping|
|
20
|
+
ping.start
|
21
|
+
ping.stop
|
18
22
|
@@twitter_pinged = true
|
19
23
|
end
|
20
24
|
end
|
@@ -27,7 +31,10 @@ describe KingKong::Runner do
|
|
27
31
|
|
28
32
|
it "should write data to socket" do
|
29
33
|
@runner.start
|
30
|
-
|
34
|
+
KingKong::Test::ReadSocket.start('/tmp/king_kong_test.socket').callback{|data|
|
35
|
+
@data = data
|
36
|
+
}
|
37
|
+
ly{ @data }.test{|data| data =~ /max/ }
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
data/spec/spec_helper.rb
CHANGED
@@ -8,5 +8,31 @@ RSpec.configure do |config|
|
|
8
8
|
config.mock_framework = :rspec
|
9
9
|
end
|
10
10
|
|
11
|
+
module KingKong
|
12
|
+
module Test
|
13
|
+
# Read data from a socket and then kill it right away.
|
14
|
+
class ReadSocket < EventMachine::Connection
|
15
|
+
include EventMachine::Deferrable
|
16
|
+
|
17
|
+
def receive_data(data)
|
18
|
+
buffer << data
|
19
|
+
end
|
20
|
+
|
21
|
+
def unbind
|
22
|
+
succeed buffer
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.start(host,port=nil)
|
26
|
+
EventMachine::connect host, port, self
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def buffer
|
31
|
+
@buffer ||= ""
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
11
37
|
# Squelch the logger so we can see our specs passing
|
12
38
|
KingKong.logger = Logger.new('/dev/null')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kingkong
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,99 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-09-16 00:00:00.000000000Z
|
14
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70359584496540 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70359584496540
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: guard-rspec
|
27
|
+
requirement: &70359584483820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70359584483820
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: growl
|
38
|
+
requirement: &70359584483400 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70359584483400
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rb-fsevent
|
49
|
+
requirement: &70359584482980 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70359584482980
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: em-ventually
|
60
|
+
requirement: &70359584482560 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70359584482560
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: timecop
|
71
|
+
requirement: &70359584482140 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70359584482140
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: ruby-debug19
|
82
|
+
requirement: &70359584481720 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70359584481720
|
15
91
|
- !ruby/object:Gem::Dependency
|
16
92
|
name: eventmachine
|
17
|
-
requirement: &
|
93
|
+
requirement: &70359584481300 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70359584481300
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: nosey
|
104
|
+
requirement: &70359584480880 !ruby/object:Gem::Requirement
|
18
105
|
none: false
|
19
106
|
requirements:
|
20
107
|
- - ! '>='
|
@@ -22,7 +109,7 @@ dependencies:
|
|
22
109
|
version: '0'
|
23
110
|
type: :runtime
|
24
111
|
prerelease: false
|
25
|
-
version_requirements: *
|
112
|
+
version_requirements: *70359584480880
|
26
113
|
description: Have you ever wanted to shoot a message throught Twitter, have your app
|
27
114
|
pick it up, do some work on it, and report how long it takes? KingKong makes it
|
28
115
|
slightly easier to do this with a DSL for writing custom pings and by providing
|
@@ -45,22 +132,17 @@ files:
|
|
45
132
|
- bin/kingkong-server
|
46
133
|
- kingkong.gemspec
|
47
134
|
- lib/kingkong.rb
|
48
|
-
- lib/kingkong/aggregator.rb
|
49
135
|
- lib/kingkong/cli.rb
|
50
136
|
- lib/kingkong/logging.rb
|
51
137
|
- lib/kingkong/ping.rb
|
52
138
|
- lib/kingkong/pinger.rb
|
53
|
-
- lib/kingkong/reporting.rb
|
54
139
|
- lib/kingkong/runner.rb
|
55
|
-
- lib/kingkong/server.rb
|
56
140
|
- lib/kingkong/version.rb
|
57
|
-
- spec/lib/kingkong/aggregator_spec.rb
|
58
141
|
- spec/lib/kingkong/ping_spec.rb
|
59
142
|
- spec/lib/kingkong/pinger_spec.rb
|
60
143
|
- spec/lib/kingkong/runner_spec.rb
|
61
144
|
- spec/lib/kingkong_spec.rb
|
62
145
|
- spec/spec_helper.rb
|
63
|
-
has_rdoc: true
|
64
146
|
homepage: ''
|
65
147
|
licenses: []
|
66
148
|
post_install_message:
|
@@ -81,12 +163,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
163
|
version: '0'
|
82
164
|
requirements: []
|
83
165
|
rubyforge_project: kingkong
|
84
|
-
rubygems_version: 1.
|
166
|
+
rubygems_version: 1.8.10
|
85
167
|
signing_key:
|
86
168
|
specification_version: 3
|
87
169
|
summary: Build complex network application health checks with Ruby and EventMachine
|
88
170
|
test_files:
|
89
|
-
- spec/lib/kingkong/aggregator_spec.rb
|
90
171
|
- spec/lib/kingkong/ping_spec.rb
|
91
172
|
- spec/lib/kingkong/pinger_spec.rb
|
92
173
|
- spec/lib/kingkong/runner_spec.rb
|
data/lib/kingkong/aggregator.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
module KingKong
|
2
|
-
# Processes and aggregates samples for reporting. These stats will probably
|
3
|
-
# be accessed throug the KingKong::Server UNIX socket.
|
4
|
-
class Aggregator
|
5
|
-
attr_reader :sum, :timed_out_count, :count, :started_at, :min, :max
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
reset
|
9
|
-
end
|
10
|
-
|
11
|
-
# Accept a ping message, keep a running total, and make sure we stay within the
|
12
|
-
# size of the number of samples that we want to keep around.
|
13
|
-
def process(*pings)
|
14
|
-
pings.each do |ping|
|
15
|
-
@count+=1
|
16
|
-
case ping.status
|
17
|
-
when :timed_out
|
18
|
-
@timed_out_count+=1
|
19
|
-
else
|
20
|
-
# This happens on our first ping before we have a min/max
|
21
|
-
@min = @max = ping.latency if @min.nil? and @max.nil?
|
22
|
-
# Cool! Lets do some math
|
23
|
-
@min = ping.latency if ping.latency < @min
|
24
|
-
@max = ping.latency if ping.latency > @max
|
25
|
-
# We need to sum latency to calculate avgs
|
26
|
-
@sum += ping.latency
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# avg latency of samples
|
32
|
-
def avg
|
33
|
-
count.zero? ? 0 : sum / count
|
34
|
-
end
|
35
|
-
|
36
|
-
# What percentage of requests are timed out?
|
37
|
-
def timed_out_percentage
|
38
|
-
timed_out_count > 0 ? timed_out_count / count : 0
|
39
|
-
end
|
40
|
-
|
41
|
-
# Basic statistical summary of ping latency
|
42
|
-
def to_hash
|
43
|
-
{
|
44
|
-
'started_at' => started_at,
|
45
|
-
'avg' => avg,
|
46
|
-
'sum' => sum,
|
47
|
-
'min' => min,
|
48
|
-
'max' => max,
|
49
|
-
'count' => count,
|
50
|
-
'timed_out_count' => timed_out_count,
|
51
|
-
'successful_count' => count - timed_out_count
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
# Print out a string for this that is suitable for flushing out to a socket
|
56
|
-
def to_s
|
57
|
-
to_hash.to_yaml
|
58
|
-
end
|
59
|
-
|
60
|
-
# Reset all of the counts to 0 and start sampling it all again!
|
61
|
-
def reset
|
62
|
-
@sum = 0.0
|
63
|
-
@min = nil
|
64
|
-
@max = nil
|
65
|
-
@count = 0
|
66
|
-
@timed_out_count = 0
|
67
|
-
@samples = Array.new
|
68
|
-
@started_at = Time.now
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/kingkong/reporting.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
|
-
module KingKong
|
4
|
-
# Provides access to the pinger via a Socket or TCP port so that other
|
5
|
-
# services, like Munin for example, can graph the data.
|
6
|
-
module Reporting
|
7
|
-
class Server < EventMachine::Connection
|
8
|
-
Terminator = "\n\n"
|
9
|
-
Host = '/tmp/king_kong.socket'
|
10
|
-
Port = nil
|
11
|
-
|
12
|
-
attr_accessor :aggregators
|
13
|
-
|
14
|
-
# Accept a collection of aggregators that we'll use to report our stats.
|
15
|
-
def initialize(*aggregators)
|
16
|
-
@aggregators = aggregators
|
17
|
-
end
|
18
|
-
|
19
|
-
# Dump out the stats and close down the connection
|
20
|
-
def post_init
|
21
|
-
begin
|
22
|
-
send_data "#{aggregators.each(&:to_s).join("\n")}#{Terminator}"
|
23
|
-
rescue => e
|
24
|
-
send_data "Exception! #{e}\n#{e.backtrace}"
|
25
|
-
ensure
|
26
|
-
close_connection
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# A nice short-cut for peeps who aren't familar with EM to fire up
|
31
|
-
# an Reporting server with an array of aggregators, host, and a port.
|
32
|
-
def self.start(aggregators, host=Socket::Host, port=Socket::Port)
|
33
|
-
EventMachine::start_server(host, port, self, aggregators)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/kingkong/server.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module KingKong
|
2
|
-
# Opens a UNIX socket to report pinger statistics
|
3
|
-
class Server < EventMachine::Connection
|
4
|
-
Frame = "\r\n"
|
5
|
-
|
6
|
-
def initialize(pinger)
|
7
|
-
@pinger = pinger
|
8
|
-
end
|
9
|
-
|
10
|
-
def post_init
|
11
|
-
send_data frame @pinger.aggregator.to_hash.to_yaml
|
12
|
-
end
|
13
|
-
|
14
|
-
# Start an instance of the aggregator server on a unix port
|
15
|
-
def self.start(pinger, host='/tmp/kingkong.socket', port=nil)
|
16
|
-
EM.start_server host, port, self, pinger
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
def frame(message)
|
21
|
-
"#{message}#{Frame}"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require "rspec/mocks/standalone"
|
3
|
-
|
4
|
-
describe KingKong::Aggregator do
|
5
|
-
before(:all) do
|
6
|
-
@agg = KingKong::Aggregator.new
|
7
|
-
|
8
|
-
@pings = (1..3).map do |n|
|
9
|
-
ping = KingKong::Ping.new
|
10
|
-
ping.stub(:latency){ n.to_f }
|
11
|
-
ping
|
12
|
-
end
|
13
|
-
|
14
|
-
@agg.process *@pings
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should calculate avg" do
|
18
|
-
@agg.avg.should eql(2.0)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should calculate sum" do
|
22
|
-
@agg.sum.should eql(6.0)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should calculate max" do
|
26
|
-
@agg.max.should eql(3.0)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should calculate min" do
|
30
|
-
@agg.min.should eql(1.0)
|
31
|
-
end
|
32
|
-
end
|