kingkong 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/kingkong.gemspec +2 -0
- data/lib/kingkong.rb +1 -0
- data/lib/kingkong/ping.rb +12 -1
- data/lib/kingkong/pinger.rb +14 -23
- data/lib/kingkong/processor.rb +80 -0
- data/lib/kingkong/runner.rb +11 -17
- data/lib/kingkong/version.rb +1 -1
- data/spec/lib/kingkong/ping_spec.rb +4 -0
- data/spec/lib/kingkong/pinger_spec.rb +24 -24
- data/spec/lib/kingkong/runner_spec.rb +9 -3
- metadata +47 -26
- data/bin/kingkong-munin +0 -18
- data/bin/kingkong-server +0 -10
data/kingkong.gemspec
CHANGED
data/lib/kingkong.rb
CHANGED
data/lib/kingkong/ping.rb
CHANGED
@@ -70,7 +70,7 @@ module KingKong
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def to_s
|
73
|
-
"Ping(#{id}, :#{status})"
|
73
|
+
"Ping(#{id}, :#{status}#{", #{latency}s" if completed?})"
|
74
74
|
end
|
75
75
|
|
76
76
|
# Generates ids for pings
|
@@ -83,6 +83,17 @@ module KingKong
|
|
83
83
|
30 # 30 seconds that is!
|
84
84
|
end
|
85
85
|
|
86
|
+
# Bust out a hash so that we can encode it into JSON and make some magic happen.
|
87
|
+
def to_hash
|
88
|
+
{
|
89
|
+
'status' => status,
|
90
|
+
'latency' => latency,
|
91
|
+
'start_time' => start_time,
|
92
|
+
'end_time' => end_time,
|
93
|
+
'ttl' => ttl
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
86
97
|
private
|
87
98
|
# Give us the current time in seconds
|
88
99
|
def current_time
|
data/lib/kingkong/pinger.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
require 'nosey'
|
3
|
+
require 'em-http-request'
|
4
|
+
require 'yajl'
|
5
|
+
require 'time'
|
3
6
|
|
4
7
|
module KingKong
|
8
|
+
# Executes pings within a specificed duration.
|
5
9
|
class Pinger
|
6
10
|
include Logging
|
7
|
-
include
|
8
|
-
|
11
|
+
include EventMachine::Deferrable
|
9
12
|
attr_reader :wait
|
10
13
|
|
11
14
|
def initialize(wait=5,&block)
|
@@ -27,22 +30,24 @@ module KingKong
|
|
27
30
|
@timer.cancel if @timer
|
28
31
|
end
|
29
32
|
|
33
|
+
# Fire this if when a ping completes
|
34
|
+
def on_ping(&block)
|
35
|
+
@on_ping = block
|
36
|
+
end
|
37
|
+
|
30
38
|
private
|
31
39
|
# Add all of the instrumentation callbacks into the ping so we can aggregate it later
|
32
40
|
def ping
|
33
41
|
ping = Ping::Deferrable.new(Ping.default_ttl, sequencer)
|
34
|
-
|
35
42
|
# Register the aggregator to process the ping
|
36
43
|
ping.callback {
|
37
|
-
logger.debug "Ping #{ping}
|
38
|
-
|
44
|
+
logger.debug "Ping #{ping}"
|
45
|
+
@on_ping.call(ping) if @on_ping
|
39
46
|
}
|
40
|
-
|
41
47
|
ping.errback {
|
42
|
-
logger.debug "Ping #{ping}
|
43
|
-
|
48
|
+
logger.debug "Ping #{ping}"
|
49
|
+
@on_ping.call(ping) if @on_ping
|
44
50
|
}
|
45
|
-
|
46
51
|
# Now pass the ping into the block so we can start/stop it
|
47
52
|
@block.call(ping, self)
|
48
53
|
end
|
@@ -51,19 +56,5 @@ module KingKong
|
|
51
56
|
def sequencer
|
52
57
|
@sequencer ||= Ping::Sequencer.new
|
53
58
|
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
|
68
59
|
end
|
69
60
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'nosey'
|
2
|
+
|
3
|
+
module KingKong
|
4
|
+
module Processor
|
5
|
+
# Base class for processing pings
|
6
|
+
class Base
|
7
|
+
# Enable block configurations
|
8
|
+
def initialize(&block)
|
9
|
+
block.call(self) if block_given?
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def process(ping)
|
14
|
+
raise 'Not Implemented'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Nosey < Base
|
19
|
+
# include ::Nosey::Instrumentation
|
20
|
+
|
21
|
+
def initialize(host='/tmp/kingkong.socket',port=nil)
|
22
|
+
EventMachine::Nosey::SocketServer.start(nosey.report, host, port)
|
23
|
+
end
|
24
|
+
|
25
|
+
def process(ping,name)
|
26
|
+
nosey.increment "#{name}_ping_count"
|
27
|
+
case ping.status
|
28
|
+
when :timed_out
|
29
|
+
nosey.increment "#{name}_ping_timed_out_count"
|
30
|
+
when :completed
|
31
|
+
nosey.increment "#{name}_ping_completed_count"
|
32
|
+
nosey.avg "#{name}_ping_avg_latency", ping.latency
|
33
|
+
nosey.min "#{name}_ping_min_latency", ping.latency
|
34
|
+
nosey.max "#{name}_ping_max_latency", ping.latency
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def nosey
|
39
|
+
@nosey ||= ::Nosey::Probe::Set.new('pinger')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Cube < Base
|
44
|
+
include Logging
|
45
|
+
|
46
|
+
attr_accessor :url
|
47
|
+
|
48
|
+
# TODO use web sockets ...
|
49
|
+
def process(ping, name)
|
50
|
+
http = EM::HttpRequest.new(url).post({
|
51
|
+
:body => Yajl::Encoder.encode([cube_hash(ping, name)]),
|
52
|
+
:head => {
|
53
|
+
'content-type' => 'application/json'
|
54
|
+
}
|
55
|
+
})
|
56
|
+
http.callback{
|
57
|
+
case http.response_header.status
|
58
|
+
when 200..204
|
59
|
+
logger.debug "Successfully reported to Cube at #{url}"
|
60
|
+
else
|
61
|
+
logger.error "Could not report to Cube server: HTTP #{http.response_header.status} : #{http.response}"
|
62
|
+
end
|
63
|
+
}
|
64
|
+
http.errback{
|
65
|
+
logger.error "Could not connect to Cube at #{url}"
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
# Bust out a hash that cube will understand as JSON
|
71
|
+
def cube_hash(ping, name)
|
72
|
+
{
|
73
|
+
'type' => name.to_s,
|
74
|
+
'time' => Time.now.iso8601,
|
75
|
+
'data' => ping.to_hash
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/kingkong/runner.rb
CHANGED
@@ -8,19 +8,25 @@ module KingKong
|
|
8
8
|
# Array of pingers that we're running
|
9
9
|
def ping(name, &block)
|
10
10
|
DSL::Pinger.new(&block).completed do |pinger|
|
11
|
-
pinger.
|
11
|
+
pinger.on_ping do |ping|
|
12
|
+
process ping, name
|
13
|
+
end
|
12
14
|
pingers << pinger
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
16
|
-
#
|
17
|
-
def
|
18
|
-
@
|
18
|
+
# We use this method to pass our pings through a processor
|
19
|
+
def process(ping, name)
|
20
|
+
@processor.call(ping,name) if @processor
|
21
|
+
end
|
22
|
+
|
23
|
+
# Configure the processor that we use to report pings
|
24
|
+
def on_pong(&block)
|
25
|
+
@processor = block
|
19
26
|
end
|
20
27
|
|
21
28
|
# Start all of the pingers given the configurations
|
22
29
|
def start
|
23
|
-
start_socket
|
24
30
|
start_pingers
|
25
31
|
end
|
26
32
|
|
@@ -50,18 +56,6 @@ module KingKong
|
|
50
56
|
end
|
51
57
|
|
52
58
|
private
|
53
|
-
# Fire up the reporting server if a socket (and port, optionally) are given
|
54
|
-
def start_socket
|
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
|
63
|
-
end
|
64
|
-
|
65
59
|
# Fire up all the pingers
|
66
60
|
def start_pingers
|
67
61
|
pingers.each(&:start)
|
data/lib/kingkong/version.rb
CHANGED
@@ -6,6 +6,10 @@ describe KingKong::Ping do
|
|
6
6
|
KingKong::Ping.new.ttl.should eql(KingKong::Ping.default_ttl)
|
7
7
|
end
|
8
8
|
|
9
|
+
it "should return hash" do
|
10
|
+
KingKong::Ping.new.to_hash.keys.should include(*%w[status latency start_time end_time ttl])
|
11
|
+
end
|
12
|
+
|
9
13
|
context "active" do
|
10
14
|
before(:each) do
|
11
15
|
@ping = KingKong::Ping.new # Open up a pinger
|
@@ -1,29 +1,29 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
|
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
|
-
|
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,8 +8,6 @@ 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/king_kong_test.socket'
|
12
|
-
|
13
11
|
runner.ping(:google).every(0.1).seconds do |ping|
|
14
12
|
ping.start
|
15
13
|
ping.stop
|
@@ -30,8 +28,16 @@ describe KingKong::Runner do
|
|
30
28
|
end
|
31
29
|
|
32
30
|
it "should write data to socket" do
|
31
|
+
nosey = KingKong::Processor::Nosey.new('/tmp/king_kong_test.socket')
|
32
|
+
|
33
|
+
@runner.on_pong do |ping, name|
|
34
|
+
nosey.process ping, name
|
35
|
+
end
|
36
|
+
|
33
37
|
@runner.start
|
34
|
-
KingKong::Test::ReadSocket.start('/tmp/king_kong_test.socket')
|
38
|
+
c = KingKong::Test::ReadSocket.start('/tmp/king_kong_test.socket')
|
39
|
+
c.send_data("READ\nQUIT\n")
|
40
|
+
c.callback{|data|
|
35
41
|
@data = data
|
36
42
|
}
|
37
43
|
ly{ @data }.test{|data| data =~ /max/ }
|
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.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-21 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: rspec
|
16
|
-
requirement: &
|
17
|
+
requirement: &70240307047860 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
20
|
- - ! '>='
|
@@ -21,10 +22,10 @@ dependencies:
|
|
21
22
|
version: '0'
|
22
23
|
type: :development
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *70240307047860
|
25
26
|
- !ruby/object:Gem::Dependency
|
26
27
|
name: guard-rspec
|
27
|
-
requirement: &
|
28
|
+
requirement: &70240307047440 !ruby/object:Gem::Requirement
|
28
29
|
none: false
|
29
30
|
requirements:
|
30
31
|
- - ! '>='
|
@@ -32,10 +33,10 @@ dependencies:
|
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
+
version_requirements: *70240307047440
|
36
37
|
- !ruby/object:Gem::Dependency
|
37
38
|
name: growl
|
38
|
-
requirement: &
|
39
|
+
requirement: &70240307047020 !ruby/object:Gem::Requirement
|
39
40
|
none: false
|
40
41
|
requirements:
|
41
42
|
- - ! '>='
|
@@ -43,10 +44,10 @@ dependencies:
|
|
43
44
|
version: '0'
|
44
45
|
type: :development
|
45
46
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
+
version_requirements: *70240307047020
|
47
48
|
- !ruby/object:Gem::Dependency
|
48
49
|
name: rb-fsevent
|
49
|
-
requirement: &
|
50
|
+
requirement: &70240307046600 !ruby/object:Gem::Requirement
|
50
51
|
none: false
|
51
52
|
requirements:
|
52
53
|
- - ! '>='
|
@@ -54,10 +55,10 @@ dependencies:
|
|
54
55
|
version: '0'
|
55
56
|
type: :development
|
56
57
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
+
version_requirements: *70240307046600
|
58
59
|
- !ruby/object:Gem::Dependency
|
59
60
|
name: em-ventually
|
60
|
-
requirement: &
|
61
|
+
requirement: &70240307046180 !ruby/object:Gem::Requirement
|
61
62
|
none: false
|
62
63
|
requirements:
|
63
64
|
- - ! '>='
|
@@ -65,10 +66,10 @@ dependencies:
|
|
65
66
|
version: '0'
|
66
67
|
type: :development
|
67
68
|
prerelease: false
|
68
|
-
version_requirements: *
|
69
|
+
version_requirements: *70240307046180
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
71
|
name: timecop
|
71
|
-
requirement: &
|
72
|
+
requirement: &70240311723120 !ruby/object:Gem::Requirement
|
72
73
|
none: false
|
73
74
|
requirements:
|
74
75
|
- - ! '>='
|
@@ -76,10 +77,10 @@ dependencies:
|
|
76
77
|
version: '0'
|
77
78
|
type: :development
|
78
79
|
prerelease: false
|
79
|
-
version_requirements: *
|
80
|
+
version_requirements: *70240311723120
|
80
81
|
- !ruby/object:Gem::Dependency
|
81
82
|
name: ruby-debug19
|
82
|
-
requirement: &
|
83
|
+
requirement: &70240311722700 !ruby/object:Gem::Requirement
|
83
84
|
none: false
|
84
85
|
requirements:
|
85
86
|
- - ! '>='
|
@@ -87,10 +88,10 @@ dependencies:
|
|
87
88
|
version: '0'
|
88
89
|
type: :development
|
89
90
|
prerelease: false
|
90
|
-
version_requirements: *
|
91
|
+
version_requirements: *70240311722700
|
91
92
|
- !ruby/object:Gem::Dependency
|
92
93
|
name: eventmachine
|
93
|
-
requirement: &
|
94
|
+
requirement: &70240311722280 !ruby/object:Gem::Requirement
|
94
95
|
none: false
|
95
96
|
requirements:
|
96
97
|
- - ! '>='
|
@@ -98,10 +99,10 @@ dependencies:
|
|
98
99
|
version: '0'
|
99
100
|
type: :runtime
|
100
101
|
prerelease: false
|
101
|
-
version_requirements: *
|
102
|
+
version_requirements: *70240311722280
|
102
103
|
- !ruby/object:Gem::Dependency
|
103
104
|
name: nosey
|
104
|
-
requirement: &
|
105
|
+
requirement: &70240311721860 !ruby/object:Gem::Requirement
|
105
106
|
none: false
|
106
107
|
requirements:
|
107
108
|
- - ! '>='
|
@@ -109,16 +110,36 @@ dependencies:
|
|
109
110
|
version: '0'
|
110
111
|
type: :runtime
|
111
112
|
prerelease: false
|
112
|
-
version_requirements: *
|
113
|
+
version_requirements: *70240311721860
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: yajl-ruby
|
116
|
+
requirement: &70240311721440 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
type: :runtime
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: *70240311721440
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: em-http-request
|
127
|
+
requirement: &70240311721020 !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :runtime
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: *70240311721020
|
113
136
|
description: Have you ever wanted to shoot a message throught Twitter, have your app
|
114
137
|
pick it up, do some work on it, and report how long it takes? KingKong makes it
|
115
138
|
slightly easier to do this with a DSL for writing custom pings and by providing
|
116
139
|
basic reporting facilities that plug into graphing applications like Munin.
|
117
140
|
email:
|
118
141
|
- brad@bradgessler.com
|
119
|
-
executables:
|
120
|
-
- kingkong-munin
|
121
|
-
- kingkong-server
|
142
|
+
executables: []
|
122
143
|
extensions: []
|
123
144
|
extra_rdoc_files: []
|
124
145
|
files:
|
@@ -128,14 +149,13 @@ files:
|
|
128
149
|
- Guardfile
|
129
150
|
- README.md
|
130
151
|
- Rakefile
|
131
|
-
- bin/kingkong-munin
|
132
|
-
- bin/kingkong-server
|
133
152
|
- kingkong.gemspec
|
134
153
|
- lib/kingkong.rb
|
135
154
|
- lib/kingkong/cli.rb
|
136
155
|
- lib/kingkong/logging.rb
|
137
156
|
- lib/kingkong/ping.rb
|
138
157
|
- lib/kingkong/pinger.rb
|
158
|
+
- lib/kingkong/processor.rb
|
139
159
|
- lib/kingkong/runner.rb
|
140
160
|
- lib/kingkong/version.rb
|
141
161
|
- spec/lib/kingkong/ping_spec.rb
|
@@ -143,6 +163,7 @@ files:
|
|
143
163
|
- spec/lib/kingkong/runner_spec.rb
|
144
164
|
- spec/lib/kingkong_spec.rb
|
145
165
|
- spec/spec_helper.rb
|
166
|
+
has_rdoc: true
|
146
167
|
homepage: ''
|
147
168
|
licenses: []
|
148
169
|
post_install_message:
|
@@ -163,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
184
|
version: '0'
|
164
185
|
requirements: []
|
165
186
|
rubyforge_project: kingkong
|
166
|
-
rubygems_version: 1.
|
187
|
+
rubygems_version: 1.6.2
|
167
188
|
signing_key:
|
168
189
|
specification_version: 3
|
169
190
|
summary: Build complex network application health checks with Ruby and EventMachine
|
data/bin/kingkong-munin
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'socket'
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
puts case ARGV.first
|
7
|
-
when /config/
|
8
|
-
%(graph_title Result latency
|
9
|
-
graph_category App
|
10
|
-
graph_vlabel load
|
11
|
-
load.label load)
|
12
|
-
else
|
13
|
-
stats = YAML.load UNIXSocket.new("/tmp/kingkong.socket").gets("\r\n")
|
14
|
-
%(load.value #{stats[:avg]})
|
15
|
-
end
|
16
|
-
|
17
|
-
# TODO - Message throughput
|
18
|
-
# TODO - Message latency (min/max/avg)
|