rstatsd 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +21 -23
- data/lib/rstatsd/chart.rb +1 -0
- data/lib/rstatsd/collector.rb +7 -11
- data/lib/rstatsd/server.rb +3 -3
- data/lib/rstatsd/version.rb +1 -1
- data/spec/rstatsd/collector_spec.rb +16 -21
- metadata +17 -17
data/README.md
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# rstatsd
|
2
2
|
|
3
|
-
rstatsd is a ruby based daemon for capturing data from statsd clients
|
3
|
+
rstatsd is a ruby based daemon for capturing data from statsd clients and
|
4
|
+
displaying graphs. It stores graph data in fixed-length data structures
|
5
|
+
in redis.
|
4
6
|
|
5
|
-
rstatsd is inspired by the work at etsy to measure
|
6
|
-
|
7
|
-
graph this data.
|
7
|
+
rstatsd is inspired by the work at etsy to measure anything, measure
|
8
|
+
everything. They use a combination of node.js and graphite to capture
|
9
|
+
and graph this data.
|
8
10
|
|
9
|
-
The goal of this project was to replicate this light-weight
|
10
|
-
|
11
|
+
The goal of this project was to replicate this approach in a very light-weight
|
12
|
+
way by reducing the number of dependencies to do this to two: redis and ruby.
|
11
13
|
|
12
14
|
## Installation
|
13
15
|
|
@@ -25,25 +27,21 @@ Start the collection daemon and server
|
|
25
27
|
|
26
28
|
$ rstatsd
|
27
29
|
|
28
|
-
|
30
|
+
Open the web server in a browser and follow the directions:
|
29
31
|
|
30
|
-
$
|
31
|
-
irb> require 'statsd'
|
32
|
-
=> true
|
33
|
-
irb> s = Statsd.new('localhost')
|
34
|
-
=> #<Statsd:0x007fee419866d8 @host="localhost", @port=8125>
|
35
|
-
irb(main):004:0> s.increment('grebulons')
|
36
|
-
=> 10
|
37
|
-
irb> s.increment('grebulons')
|
38
|
-
=> 10
|
39
|
-
irb> s.increment('grebulons')
|
40
|
-
=> 10
|
41
|
-
irb> s.increment('grebulons')
|
42
|
-
=> 10
|
32
|
+
$ open http://localhost:8126/
|
43
33
|
|
34
|
+
## URL Schema
|
44
35
|
|
45
|
-
|
36
|
+
You can request multiple data points to be graphed simultaneously by specifying multiple targets:
|
46
37
|
|
47
|
-
|
38
|
+
http://localhost:8126/stats?target=foo&target=bar
|
48
39
|
|
49
|
-
|
40
|
+
## Supported data types
|
41
|
+
|
42
|
+
* counters (statsd.increment, statsd.decrement)
|
43
|
+
|
44
|
+
## Todo
|
45
|
+
|
46
|
+
* statsd data types other than counters
|
47
|
+
* time window graphing
|
data/lib/rstatsd/chart.rb
CHANGED
data/lib/rstatsd/collector.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'em-hiredis'
|
2
1
|
require_relative './helpers'
|
3
2
|
|
4
3
|
module Rstatsd
|
@@ -7,7 +6,6 @@ module Rstatsd
|
|
7
6
|
|
8
7
|
def initialize
|
9
8
|
super
|
10
|
-
@redis = EM::Hiredis.connect
|
11
9
|
end
|
12
10
|
|
13
11
|
def post_init
|
@@ -21,19 +19,17 @@ module Rstatsd
|
|
21
19
|
case fields[1]
|
22
20
|
when 'c'
|
23
21
|
if fields[0] == '1'
|
24
|
-
|
25
|
-
|
26
|
-
end
|
22
|
+
value = redis.incr(key)
|
23
|
+
redis.rpush(counter_key_name(key), "#{value}:#{Time.now.to_i}")
|
27
24
|
elsif fields[0] == '-1'
|
28
|
-
|
29
|
-
|
30
|
-
end
|
25
|
+
value = redis.decr(key)
|
26
|
+
redis.rpush(counter_key_name(key), "#{value}:#{Time.now.to_i}")
|
31
27
|
end
|
32
|
-
|
28
|
+
redis.ltrim(counter_key_name(key), -10000, -1)
|
33
29
|
when 'ms'
|
34
30
|
#update timer
|
35
|
-
|
36
|
-
|
31
|
+
redis.rpush(timer_key_name(key), "#{fields[0]}:#{Time.now.to_i}")
|
32
|
+
redis.ltrim(timer_key_name(key), -10000, -1)
|
37
33
|
else
|
38
34
|
# invalid update
|
39
35
|
end
|
data/lib/rstatsd/server.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'eventmachine'
|
2
2
|
require 'eventmachine_httpserver'
|
3
3
|
require 'evma_httpserver/response'
|
4
4
|
require 'erb'
|
@@ -26,8 +26,8 @@ module Rstatsd
|
|
26
26
|
when '/stats'
|
27
27
|
Rstatsd::Chart.new(@http_query_string).draw_chart do |chart|
|
28
28
|
@chart = chart
|
29
|
-
google_chart = ERB.new(File.open('templates/google_chart.erb').read).
|
30
|
-
|
29
|
+
google_chart = ERB.new(File.open('templates/google_chart.erb').read).
|
30
|
+
result(binding)
|
31
31
|
response.content_type 'text/html'
|
32
32
|
response.content = google_chart
|
33
33
|
response.send_response
|
data/lib/rstatsd/version.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Rstatsd::Collector do
|
4
|
-
let(:
|
4
|
+
let(:redis) {
|
5
5
|
stub.as_null_object
|
6
6
|
}
|
7
7
|
|
8
|
-
let(:redis_result) {
|
9
|
-
redis_result = stub
|
10
|
-
}
|
11
|
-
|
12
8
|
before do
|
13
|
-
|
9
|
+
Redis.stub(:new).and_return(redis)
|
14
10
|
end
|
15
11
|
|
16
12
|
context "receiving an increment packet 'crumdingler:1|c'" do
|
17
13
|
it "should increment the counter stored at the keyname" do
|
18
14
|
with_em_connection do
|
19
|
-
|
15
|
+
redis.should_receive(:incr).with('crumdingler').and_return(stub.as_null_object)
|
20
16
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:1|c')
|
21
17
|
end
|
22
18
|
end
|
@@ -24,9 +20,10 @@ describe Rstatsd::Collector do
|
|
24
20
|
it "should rpush the counter value into redis" do
|
25
21
|
with_em_connection do
|
26
22
|
Timecop.freeze(Time.now) do
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
redis.should_receive(:incr).with('crumdingler').and_return('1')
|
24
|
+
redis.should_receive(:rpush).
|
25
|
+
with('counter:crumdingler', "1:#{Time.now.to_i}").
|
26
|
+
and_return(stub.as_null_object)
|
30
27
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:1|c')
|
31
28
|
end
|
32
29
|
end
|
@@ -34,17 +31,15 @@ describe Rstatsd::Collector do
|
|
34
31
|
|
35
32
|
it "should trim the overall size of the counter list to 10000 entries" do
|
36
33
|
with_em_connection do
|
37
|
-
|
34
|
+
redis.should_receive(:ltrim).with('counter:crumdingler', -10000, -1)
|
38
35
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:1|c')
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
39
|
it "should rpush the incremented value onto a list in the format counter:keyname" do
|
43
40
|
with_em_connection do
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
hiredis.should_receive(:rpush).with('counter:crumdingler', anything)
|
41
|
+
redis.stub(:incr)
|
42
|
+
redis.should_receive(:rpush).with('counter:crumdingler', anything)
|
48
43
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:1|c')
|
49
44
|
end
|
50
45
|
end
|
@@ -56,17 +51,17 @@ describe Rstatsd::Collector do
|
|
56
51
|
context "decrementing a value" do
|
57
52
|
it "should decrement the counter stored at the keyname" do
|
58
53
|
with_em_connection do
|
59
|
-
|
60
|
-
Rstatsd::Collector.new(stub).receive_data('crumdingler
|
54
|
+
redis.should_receive(:decr).with('crumdingler')
|
55
|
+
Rstatsd::Collector.new(stub).receive_data('crumdingler:-1|c')
|
61
56
|
end
|
62
57
|
end
|
63
58
|
|
64
59
|
it "should rpush the returned counter value into redis" do
|
65
60
|
with_em_connection do
|
66
61
|
Timecop.freeze(Time.now) do
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
redis.stub(:decr).and_return('-1')
|
63
|
+
redis.should_receive(:rpush).
|
64
|
+
with('counter:crumdingler', "-1:#{Time.now.to_i}")
|
70
65
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:-1|c')
|
71
66
|
end
|
72
67
|
end
|
@@ -74,7 +69,7 @@ describe Rstatsd::Collector do
|
|
74
69
|
|
75
70
|
it "should trim the overall size of the counter list to 10000 entries" do
|
76
71
|
with_em_connection do
|
77
|
-
|
72
|
+
redis.should_receive(:ltrim).with('counter:crumdingler', -10000, -1)
|
78
73
|
Rstatsd::Collector.new(stub).receive_data('crumdingler:-1|c')
|
79
74
|
end
|
80
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rstatsd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-22 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70359047813080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70359047813080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hiredis
|
27
|
-
requirement: &
|
27
|
+
requirement: &70359047812660 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70359047812660
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: eventmachine
|
38
|
-
requirement: &
|
38
|
+
requirement: &70359047812240 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70359047812240
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: eventmachine_httpserver
|
49
|
-
requirement: &
|
49
|
+
requirement: &70359047811820 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70359047811820
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &70359047811400 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70359047811400
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: timecop
|
71
|
-
requirement: &
|
71
|
+
requirement: &70359047810980 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70359047810980
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: statsd-ruby
|
82
|
-
requirement: &
|
82
|
+
requirement: &70359047810560 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70359047810560
|
91
91
|
description: a stats daemon that stores data in redis
|
92
92
|
email:
|
93
93
|
- whoahbot@gmail.com
|
@@ -144,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: '0'
|
145
145
|
requirements: []
|
146
146
|
rubyforge_project:
|
147
|
-
rubygems_version: 1.8.
|
147
|
+
rubygems_version: 1.8.16
|
148
148
|
signing_key:
|
149
149
|
specification_version: 3
|
150
150
|
summary: rstatsd is a simpler ruby implementaiton of statsd, storing the data in redis
|