kingkong 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,4 +28,6 @@ Gem::Specification.new do |s|
28
28
 
29
29
  s.add_runtime_dependency "eventmachine"
30
30
  s.add_runtime_dependency "nosey"
31
+ s.add_runtime_dependency "yajl-ruby"
32
+ s.add_runtime_dependency "em-http-request"
31
33
  end
@@ -6,6 +6,7 @@ module KingKong
6
6
  autoload :Runner, 'kingkong/runner'
7
7
  autoload :Logging, 'kingkong/logging'
8
8
  autoload :Aggregator, 'kingkong/aggregator'
9
+ autoload :Processor, 'kingkong/processor'
9
10
 
10
11
  # Default logger for KingKong.
11
12
  def self.logger
@@ -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
@@ -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 Nosey::Instrumentation
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} successful"
38
- process ping
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} error (probably a timeout)"
43
- process ping
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
@@ -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.nosey.name = name.to_s
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
- # Setup the socket that this thing will write stats out to
17
- def socket(host='/tmp/king_kong.socket', port=nil)
18
- @socket_host , @socket_port = host, port
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)
@@ -1,3 +1,3 @@
1
1
  module KingKong
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -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
- # require 'spec_helper'
1
+ require 'spec_helper'
2
2
 
3
- # describe KingKong::Pinger do
4
- # include EM::Ventually
3
+ describe KingKong::Pinger do
4
+ include EM::Ventually
5
5
 
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
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
- # it "should ping" do
17
- # @pinger.start
18
- # ly(:completed) { @@ping.status }
19
- # end
16
+ it "should ping" do
17
+ @pinger.start
18
+ ly(:completed) { @@ping.status }
19
+ end
20
20
 
21
- # it "should stop"
22
- # it "should start"
21
+ it "should stop"
22
+ it "should start"
23
23
 
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
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').callback{|data|
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.7
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-16 00:00:00.000000000Z
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: &70359584496540 !ruby/object:Gem::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: *70359584496540
25
+ version_requirements: *70240307047860
25
26
  - !ruby/object:Gem::Dependency
26
27
  name: guard-rspec
27
- requirement: &70359584483820 !ruby/object:Gem::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: *70359584483820
36
+ version_requirements: *70240307047440
36
37
  - !ruby/object:Gem::Dependency
37
38
  name: growl
38
- requirement: &70359584483400 !ruby/object:Gem::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: *70359584483400
47
+ version_requirements: *70240307047020
47
48
  - !ruby/object:Gem::Dependency
48
49
  name: rb-fsevent
49
- requirement: &70359584482980 !ruby/object:Gem::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: *70359584482980
58
+ version_requirements: *70240307046600
58
59
  - !ruby/object:Gem::Dependency
59
60
  name: em-ventually
60
- requirement: &70359584482560 !ruby/object:Gem::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: *70359584482560
69
+ version_requirements: *70240307046180
69
70
  - !ruby/object:Gem::Dependency
70
71
  name: timecop
71
- requirement: &70359584482140 !ruby/object:Gem::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: *70359584482140
80
+ version_requirements: *70240311723120
80
81
  - !ruby/object:Gem::Dependency
81
82
  name: ruby-debug19
82
- requirement: &70359584481720 !ruby/object:Gem::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: *70359584481720
91
+ version_requirements: *70240311722700
91
92
  - !ruby/object:Gem::Dependency
92
93
  name: eventmachine
93
- requirement: &70359584481300 !ruby/object:Gem::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: *70359584481300
102
+ version_requirements: *70240311722280
102
103
  - !ruby/object:Gem::Dependency
103
104
  name: nosey
104
- requirement: &70359584480880 !ruby/object:Gem::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: *70359584480880
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.8.10
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
@@ -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)
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'bundler/setup'
5
- require 'kingkong'
6
-
7
- EventMachine::run do
8
- trap('TERM') { EM.stop }
9
- trap('INT') { EM.stop }
10
- end