daikon 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -2
- data/Gemfile.lock +2 -0
- data/daikon.gemspec +14 -9
- data/lib/daikon.rb +2 -1
- data/lib/daikon/client.rb +10 -15
- data/lib/daikon/monitor.rb +37 -0
- data/spec/client_spec.rb +13 -9
- data/spec/monitor_spec.rb +96 -0
- data/spec/spec_helper.rb +1 -0
- metadata +24 -8
- data/VERSION +0 -1
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -39,6 +39,7 @@ GEM
|
|
39
39
|
diff-lcs (~> 1.1.2)
|
40
40
|
rspec-mocks (2.1.0)
|
41
41
|
term-ansicolor (1.0.5)
|
42
|
+
timecop (0.3.5)
|
42
43
|
webmock (1.6.1)
|
43
44
|
addressable (>= 2.2.2)
|
44
45
|
crack (>= 0.1.7)
|
@@ -56,4 +57,5 @@ DEPENDENCIES
|
|
56
57
|
net-http-persistent (~> 1.4.1)
|
57
58
|
redis (~> 2.1.1)
|
58
59
|
rspec
|
60
|
+
timecop
|
59
61
|
webmock
|
data/daikon.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{daikon}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nick Quaranto"]
|
12
|
-
s.date = %q{2010-12-
|
12
|
+
s.date = %q{2010-12-12}
|
13
13
|
s.default_executable = %q{daikon}
|
14
14
|
s.description = %q{daikon, a radishapp.com client}
|
15
15
|
s.email = %q{nick@quaran.to}
|
@@ -25,7 +25,6 @@ Gem::Specification.new do |s|
|
|
25
25
|
"MIT-LICENSE",
|
26
26
|
"README.rdoc",
|
27
27
|
"Rakefile",
|
28
|
-
"VERSION",
|
29
28
|
"bin/daikon",
|
30
29
|
"daikon.gemspec",
|
31
30
|
"features/daikon.feature",
|
@@ -35,12 +34,14 @@ Gem::Specification.new do |s|
|
|
35
34
|
"lib/daikon/client.rb",
|
36
35
|
"lib/daikon/configuration.rb",
|
37
36
|
"lib/daikon/daemon.rb",
|
37
|
+
"lib/daikon/monitor.rb",
|
38
38
|
"lib/daikon/namespace_tools.rb",
|
39
39
|
"lib/daikon/redis_hacks.rb",
|
40
40
|
"spec/client_spec.rb",
|
41
41
|
"spec/configuration_spec.rb",
|
42
42
|
"spec/daemon_spec.rb",
|
43
43
|
"spec/daikon_spec.rb",
|
44
|
+
"spec/monitor_spec.rb",
|
44
45
|
"spec/spec_helper.rb"
|
45
46
|
]
|
46
47
|
s.homepage = %q{http://github.com/qrush/daikon}
|
@@ -53,6 +54,7 @@ Gem::Specification.new do |s|
|
|
53
54
|
"spec/configuration_spec.rb",
|
54
55
|
"spec/daemon_spec.rb",
|
55
56
|
"spec/daikon_spec.rb",
|
57
|
+
"spec/monitor_spec.rb",
|
56
58
|
"spec/spec_helper.rb"
|
57
59
|
]
|
58
60
|
|
@@ -66,10 +68,11 @@ Gem::Specification.new do |s|
|
|
66
68
|
s.add_runtime_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
67
69
|
s.add_runtime_dependency(%q<redis>, ["~> 2.1.1"])
|
68
70
|
s.add_runtime_dependency(%q<SystemTimer>, ["~> 1.2.1"])
|
69
|
-
s.add_development_dependency(%q<
|
71
|
+
s.add_development_dependency(%q<bourne>, [">= 0"])
|
70
72
|
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
71
73
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
72
|
-
s.add_development_dependency(%q<
|
74
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
75
|
+
s.add_development_dependency(%q<timecop>, [">= 0"])
|
73
76
|
s.add_development_dependency(%q<webmock>, [">= 0"])
|
74
77
|
else
|
75
78
|
s.add_dependency(%q<daemons>, ["~> 1.1.0"])
|
@@ -77,10 +80,11 @@ Gem::Specification.new do |s|
|
|
77
80
|
s.add_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
78
81
|
s.add_dependency(%q<redis>, ["~> 2.1.1"])
|
79
82
|
s.add_dependency(%q<SystemTimer>, ["~> 1.2.1"])
|
80
|
-
s.add_dependency(%q<
|
83
|
+
s.add_dependency(%q<bourne>, [">= 0"])
|
81
84
|
s.add_dependency(%q<cucumber>, [">= 0"])
|
82
85
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
83
|
-
s.add_dependency(%q<
|
86
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
87
|
+
s.add_dependency(%q<timecop>, [">= 0"])
|
84
88
|
s.add_dependency(%q<webmock>, [">= 0"])
|
85
89
|
end
|
86
90
|
else
|
@@ -89,10 +93,11 @@ Gem::Specification.new do |s|
|
|
89
93
|
s.add_dependency(%q<net-http-persistent>, ["~> 1.4.1"])
|
90
94
|
s.add_dependency(%q<redis>, ["~> 2.1.1"])
|
91
95
|
s.add_dependency(%q<SystemTimer>, ["~> 1.2.1"])
|
92
|
-
s.add_dependency(%q<
|
96
|
+
s.add_dependency(%q<bourne>, [">= 0"])
|
93
97
|
s.add_dependency(%q<cucumber>, [">= 0"])
|
94
98
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
95
|
-
s.add_dependency(%q<
|
99
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
100
|
+
s.add_dependency(%q<timecop>, [">= 0"])
|
96
101
|
s.add_dependency(%q<webmock>, [">= 0"])
|
97
102
|
end
|
98
103
|
end
|
data/lib/daikon.rb
CHANGED
data/lib/daikon/client.rb
CHANGED
@@ -15,10 +15,11 @@ module Daikon
|
|
15
15
|
attr_accessor :redis, :logger, :config, :http, :monitor
|
16
16
|
|
17
17
|
def setup(config, logger = nil)
|
18
|
-
self.config
|
19
|
-
self.logger
|
20
|
-
self.redis
|
21
|
-
self.http
|
18
|
+
self.config = config
|
19
|
+
self.logger = logger
|
20
|
+
self.redis = connect
|
21
|
+
self.http = Net::HTTP::Persistent.new
|
22
|
+
self.monitor = Monitor.new(connect, logger)
|
22
23
|
http.headers['Authorization'] = config.api_key
|
23
24
|
|
24
25
|
log "Started Daikon v#{VERSION}"
|
@@ -29,12 +30,7 @@ module Daikon
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def start_monitor
|
32
|
-
|
33
|
-
Thread.new do
|
34
|
-
connect.monitor do |line|
|
35
|
-
monitor.puts line
|
36
|
-
end
|
37
|
-
end
|
33
|
+
monitor.start
|
38
34
|
end
|
39
35
|
|
40
36
|
def log(message)
|
@@ -82,13 +78,12 @@ module Daikon
|
|
82
78
|
end
|
83
79
|
|
84
80
|
def rotate_monitor
|
85
|
-
|
86
|
-
monitor.reopen(StringIO.new)
|
81
|
+
lines = monitor.rotate
|
87
82
|
|
88
|
-
http_request(:post, "api/v1/monitor") do |request|
|
89
|
-
request.body =
|
83
|
+
http_request(:post, "api/v1/monitor.json") do |request|
|
84
|
+
request.body = {"lines" => lines}.to_json
|
90
85
|
request.add_field "Content-Length", request.body.size.to_s
|
91
|
-
request.add_field "Content-Type", "application/
|
86
|
+
request.add_field "Content-Type", "application/json"
|
92
87
|
end
|
93
88
|
rescue *EXCEPTIONS => ex
|
94
89
|
log ex.to_s
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Daikon
|
2
|
+
class Monitor
|
3
|
+
attr_accessor :queue
|
4
|
+
|
5
|
+
NEW_FORMAT = /^(\d+\.\d+)( "[A-Z]+".*)/i
|
6
|
+
OLD_SINGLE_FORMAT = /^(QUIT|RANDOMKEY|DBSIZE|EXPIRE|TTL|SAVE|BGSAVE|SHUTDOWN|BGREWRITEAOF|INFO|MONITOR|SLAVEOF)$/i
|
7
|
+
OLD_MORE_FORMAT = /^[A-Z]+ .*$/i
|
8
|
+
|
9
|
+
def initialize(redis = nil, logger = nil)
|
10
|
+
@queue = []
|
11
|
+
@redis = redis
|
12
|
+
@logger = logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
Thread.new do
|
17
|
+
@redis.monitor do |line|
|
18
|
+
parse(line)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def rotate
|
24
|
+
@queue.shift(@queue.size)
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse(line)
|
28
|
+
if line =~ NEW_FORMAT
|
29
|
+
timestamp = $1
|
30
|
+
line = $2.strip
|
31
|
+
@queue.push({:at => Time.at(*timestamp.split('.').map(&:to_i)), :command => line})
|
32
|
+
elsif line =~ OLD_SINGLE_FORMAT || line =~ OLD_MORE_FORMAT
|
33
|
+
@queue.push({:at => Time.now, :command => line.strip})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -18,7 +18,7 @@ describe Daikon::Client, "setup" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "sets redis to listen on the given port" do
|
21
|
-
Redis.should have_received(:new).with(:host => "8.8.8.8", :port => "1234")
|
21
|
+
Redis.should have_received(:new).with(:host => "8.8.8.8", :port => "1234").twice
|
22
22
|
subject.should have_received(:redis=).with(redis)
|
23
23
|
end
|
24
24
|
end
|
@@ -31,7 +31,7 @@ describe Daikon::Client, "setup" do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "sets redis to listen on the given port" do
|
34
|
-
Redis.should have_received(:new).with(:host => "127.0.0.1", :port => "6379")
|
34
|
+
Redis.should have_received(:new).with(:host => "127.0.0.1", :port => "6379").twice
|
35
35
|
subject.should have_received(:redis=).with(redis)
|
36
36
|
end
|
37
37
|
end
|
@@ -168,16 +168,16 @@ end
|
|
168
168
|
|
169
169
|
shared_examples_for "a monitor api consumer" do
|
170
170
|
it "shoots the results back to radish" do
|
171
|
-
|
171
|
+
payload = {"lines" => lines}
|
172
172
|
|
173
173
|
headers = {
|
174
174
|
"Authorization" => api_key,
|
175
|
-
"Content-Length" =>
|
176
|
-
"Content-Type" => "application/
|
175
|
+
"Content-Length" => payload.to_json.size,
|
176
|
+
"Content-Type" => "application/json"
|
177
177
|
}
|
178
178
|
|
179
|
-
WebMock.should have_requested(:post, "#{server}/api/v1/monitor").
|
180
|
-
with(:body =>
|
179
|
+
WebMock.should have_requested(:post, "#{server}/api/v1/monitor.json").
|
180
|
+
with(:body => payload.to_json, :headers => headers)
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
@@ -185,11 +185,15 @@ describe Daikon::Client, "rotate monitor" do
|
|
185
185
|
subject { Daikon::Client.new }
|
186
186
|
let(:results) { %{1290289048.96581 "info"\n1290289053.568815 "info"} }
|
187
187
|
let(:redis) { stub("redis instance", :info => results) }
|
188
|
+
let(:lines) do
|
189
|
+
[{"at" => Time.at(1290289048, 96581), "command" => "info"},
|
190
|
+
{"at" => Time.at(1290289053, 568815), "command" => "info"}]
|
191
|
+
end
|
188
192
|
|
189
193
|
before do
|
190
|
-
stub_request(:post, "#{server}/api/v1/monitor")
|
191
|
-
subject.monitor = StringIO.new(results)
|
194
|
+
stub_request(:post, "#{server}/api/v1/monitor.json")
|
192
195
|
subject.setup(config)
|
196
|
+
subject.monitor = stub("monitor", :rotate => lines)
|
193
197
|
subject.rotate_monitor
|
194
198
|
end
|
195
199
|
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Daikon::Monitor, "#rotate" do
|
4
|
+
it "pops off what is on the queue" do
|
5
|
+
subject.parse("INCR foo")
|
6
|
+
subject.parse("DECR foo")
|
7
|
+
|
8
|
+
data = subject.rotate
|
9
|
+
data.first[:command].should == "INCR foo"
|
10
|
+
data.last[:command].should == "DECR foo"
|
11
|
+
data.size.should == 2
|
12
|
+
subject.queue.size.should be_zero
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Daikon::Monitor, "#parse with new format" do
|
17
|
+
subject { Daikon::Monitor.new }
|
18
|
+
let(:line) { '1291699658.994073 "decrby" "fooz" "2000"' }
|
19
|
+
|
20
|
+
it "parses the log into json" do
|
21
|
+
subject.parse(line)
|
22
|
+
subject.queue.should include({:at => Time.at(1291699658, 994073), :command => '"decrby" "fooz" "2000"'})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Daikon::Monitor, "#parse with multiple inputs" do
|
27
|
+
subject { Daikon::Monitor.new }
|
28
|
+
before { Timecop.freeze }
|
29
|
+
after { Timecop.return }
|
30
|
+
|
31
|
+
it "queues up multiple lines" do
|
32
|
+
subject.parse("+OK")
|
33
|
+
subject.parse("INCR foo")
|
34
|
+
subject.parse("INCR fooz")
|
35
|
+
subject.parse("info")
|
36
|
+
|
37
|
+
subject.queue.size.should == 3
|
38
|
+
subject.queue.should include({:at => Time.now, :command => 'INCR foo'})
|
39
|
+
subject.queue.should include({:at => Time.now, :command => 'INCR fooz'})
|
40
|
+
subject.queue.should include({:at => Time.now, :command => 'info'})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Daikon::Monitor, "#parse with old multi line input" do
|
45
|
+
subject { Daikon::Monitor.new }
|
46
|
+
before { Timecop.freeze }
|
47
|
+
after { Timecop.return }
|
48
|
+
|
49
|
+
it "parses gzipped logs into raws" do
|
50
|
+
subject.parse("incr foo")
|
51
|
+
subject.parse("sismember project-13897-global-error-classes 17")
|
52
|
+
subject.parse("incrApiParameterError")
|
53
|
+
subject.parse("decr foo")
|
54
|
+
|
55
|
+
subject.queue.size.should == 3
|
56
|
+
subject.queue.should include({:at => Time.now, :command => 'incr foo'})
|
57
|
+
subject.queue.should include({:at => Time.now, :command => 'sismember project-13897-global-error-classes 17'})
|
58
|
+
subject.queue.should include({:at => Time.now, :command => 'decr foo'})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe Daikon::Monitor, "#parse with multi line input with numbers" do
|
63
|
+
subject { Daikon::Monitor.new }
|
64
|
+
before { Timecop.freeze }
|
65
|
+
after { Timecop.return }
|
66
|
+
|
67
|
+
it "parses gzipped logs into raws" do
|
68
|
+
subject.parse("incr foo")
|
69
|
+
subject.parse("set g:2470920:mrn 9")
|
70
|
+
subject.parse("554079885")
|
71
|
+
subject.parse("decr foo")
|
72
|
+
|
73
|
+
subject.queue.size.should == 3
|
74
|
+
subject.queue.should include({:at => Time.now, :command => 'incr foo'})
|
75
|
+
subject.queue.should include({:at => Time.now, :command => 'set g:2470920:mrn 9'})
|
76
|
+
subject.queue.should include({:at => Time.now, :command => 'decr foo'})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Daikon::Monitor, "#parse with strings that may to_i to a number" do
|
81
|
+
subject { Daikon::Monitor.new }
|
82
|
+
before { Timecop.freeze }
|
83
|
+
after { Timecop.return }
|
84
|
+
|
85
|
+
it "parses gzipped logs into raws" do
|
86
|
+
subject.parse("incr foo")
|
87
|
+
subject.parse("set g:2470920:mrn 9")
|
88
|
+
subject.parse("46fdcf77c1bb2108e6191602c2f5f9ae")
|
89
|
+
subject.parse("decr foo")
|
90
|
+
|
91
|
+
subject.queue.size.should == 3
|
92
|
+
subject.queue.should include({:at => Time.now, :command => 'incr foo'})
|
93
|
+
subject.queue.should include({:at => Time.now, :command => 'set g:2470920:mrn 9'})
|
94
|
+
subject.queue.should include({:at => Time.now, :command => 'decr foo'})
|
95
|
+
end
|
96
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: daikon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Nick Quaranto
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-12 00:00:00 -05:00
|
19
19
|
default_executable: daikon
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -101,7 +101,7 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
102
|
prerelease: false
|
103
103
|
type: :development
|
104
|
-
name:
|
104
|
+
name: bourne
|
105
105
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
106
106
|
none: false
|
107
107
|
requirements:
|
@@ -143,7 +143,7 @@ dependencies:
|
|
143
143
|
- !ruby/object:Gem::Dependency
|
144
144
|
prerelease: false
|
145
145
|
type: :development
|
146
|
-
name:
|
146
|
+
name: rspec
|
147
147
|
version_requirements: &id009 !ruby/object:Gem::Requirement
|
148
148
|
none: false
|
149
149
|
requirements:
|
@@ -157,7 +157,7 @@ dependencies:
|
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
prerelease: false
|
159
159
|
type: :development
|
160
|
-
name:
|
160
|
+
name: timecop
|
161
161
|
version_requirements: &id010 !ruby/object:Gem::Requirement
|
162
162
|
none: false
|
163
163
|
requirements:
|
@@ -168,6 +168,20 @@ dependencies:
|
|
168
168
|
- 0
|
169
169
|
version: "0"
|
170
170
|
requirement: *id010
|
171
|
+
- !ruby/object:Gem::Dependency
|
172
|
+
prerelease: false
|
173
|
+
type: :development
|
174
|
+
name: webmock
|
175
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
176
|
+
none: false
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
hash: 3
|
181
|
+
segments:
|
182
|
+
- 0
|
183
|
+
version: "0"
|
184
|
+
requirement: *id011
|
171
185
|
description: daikon, a radishapp.com client
|
172
186
|
email: nick@quaran.to
|
173
187
|
executables:
|
@@ -184,7 +198,6 @@ files:
|
|
184
198
|
- MIT-LICENSE
|
185
199
|
- README.rdoc
|
186
200
|
- Rakefile
|
187
|
-
- VERSION
|
188
201
|
- bin/daikon
|
189
202
|
- daikon.gemspec
|
190
203
|
- features/daikon.feature
|
@@ -194,12 +207,14 @@ files:
|
|
194
207
|
- lib/daikon/client.rb
|
195
208
|
- lib/daikon/configuration.rb
|
196
209
|
- lib/daikon/daemon.rb
|
210
|
+
- lib/daikon/monitor.rb
|
197
211
|
- lib/daikon/namespace_tools.rb
|
198
212
|
- lib/daikon/redis_hacks.rb
|
199
213
|
- spec/client_spec.rb
|
200
214
|
- spec/configuration_spec.rb
|
201
215
|
- spec/daemon_spec.rb
|
202
216
|
- spec/daikon_spec.rb
|
217
|
+
- spec/monitor_spec.rb
|
203
218
|
- spec/spec_helper.rb
|
204
219
|
has_rdoc: true
|
205
220
|
homepage: http://github.com/qrush/daikon
|
@@ -240,4 +255,5 @@ test_files:
|
|
240
255
|
- spec/configuration_spec.rb
|
241
256
|
- spec/daemon_spec.rb
|
242
257
|
- spec/daikon_spec.rb
|
258
|
+
- spec/monitor_spec.rb
|
243
259
|
- spec/spec_helper.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.0
|