redistat 0.0.1

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.
@@ -0,0 +1,112 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Finder do
4
+ include Redistat::Database
5
+
6
+ before(:each) do
7
+ db.flushdb
8
+ @scope = "PageViews"
9
+ @label = "about_us"
10
+ @date = Time.now
11
+ @key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
12
+ @stats = {"views" => 3, "visitors" => 2}
13
+ end
14
+
15
+ it "should initialize properly" do
16
+ two_hours_ago = 2.hours.ago
17
+ one_hour_ago = 1.hour.ago
18
+ options = {:scope => "PageViews", :label => "Label", :from => two_hours_ago, :till => one_hour_ago, :depth => :hour, :interval => :hour}
19
+
20
+ finder = Redistat::Finder.new(options)
21
+ finder.options.should == options
22
+
23
+ finder = Redistat::Finder.dates(two_hours_ago, one_hour_ago).scope("PageViews").label("Label").depth(:hour).interval(:hour)
24
+ finder.options.should == options
25
+
26
+ finder = Redistat::Finder.scope("PageViews").label("Label").from(two_hours_ago).till(one_hour_ago).depth(:hour).interval(:hour)
27
+ finder.options.should == options
28
+
29
+ finder = Redistat::Finder.label("Label").from(two_hours_ago).till(one_hour_ago).depth(:hour).interval(:hour).scope("PageViews")
30
+ finder.options.should == options
31
+
32
+ finder = Redistat::Finder.from(two_hours_ago).till(one_hour_ago).depth(:hour).interval(:hour).scope("PageViews").label("Label")
33
+ finder.options.should == options
34
+
35
+ finder = Redistat::Finder.till(one_hour_ago).depth(:hour).interval(:hour).scope("PageViews").label("Label").from(two_hours_ago)
36
+ finder.options.should == options
37
+
38
+ finder = Redistat::Finder.depth(:hour).interval(:hour).scope("PageViews").label("Label").from(two_hours_ago).till(one_hour_ago)
39
+ finder.options.should == options
40
+
41
+ finder = Redistat::Finder.interval(:hour).scope("PageViews").label("Label").from(two_hours_ago).till(one_hour_ago).depth(:hour)
42
+ finder.options.should == options
43
+
44
+ end
45
+
46
+ it "should fetch stats properly" do
47
+ first_stat, last_stat = create_example_stats
48
+
49
+ stats = Redistat::Finder.find({:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour})
50
+ stats.from.should == first_stat
51
+ stats.till.should == last_stat
52
+ stats.depth.should == :hour
53
+
54
+ stats.total.should == { "views" => 12, "visitors" => 8 }
55
+ stats.total.from.should == first_stat
56
+ stats.total.till.should == last_stat
57
+ stats.first.should == stats.total
58
+ end
59
+
60
+ it "should fetch data per unit when interval option is specified" do
61
+ first_stat, last_stat = create_example_stats
62
+
63
+ stats = Redistat::Finder.find(:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour, :interval => :hour)
64
+ stats.from.should == first_stat
65
+ stats.till.should == last_stat
66
+ stats.total.should == { "views" => 12, "visitors" => 8 }
67
+ stats[0].should == {}
68
+ stats[0].date.should == Time.parse("2010-05-14 12:00")
69
+ stats[1].should == {"visitors"=>"4", "views"=>"6"}
70
+ stats[1].date.should == Time.parse("2010-05-14 13:00")
71
+ stats[2].should == {"visitors"=>"2", "views"=>"3"}
72
+ stats[2].date.should == Time.parse("2010-05-14 14:00")
73
+ stats[3].should == {"visitors"=>"2", "views"=>"3"}
74
+ stats[3].date.should == Time.parse("2010-05-14 15:00")
75
+ stats[4].should == {}
76
+ stats[4].date.should == Time.parse("2010-05-14 16:00")
77
+ end
78
+
79
+ it "should return empty hash when attempting to fetch non-existent results" do
80
+ stats = Redistat::Finder.find({:from => 3.hours.ago, :till => 2.hours.from_now, :scope => @scope, :label => @label, :depth => :hour})
81
+ stats.total.should == {}
82
+ end
83
+
84
+ it "should throw error on invalid options" do
85
+ lambda { Redistat::Finder.find(:from => 3.hours.ago) }.should raise_error(Redistat::InvalidOptions)
86
+ end
87
+
88
+
89
+ # helper methods
90
+
91
+ def create_example_stats
92
+ key = Redistat::Key.new(@scope, @label, (first = Time.parse("2010-05-14 13:43")))
93
+ Redistat::Summary.update(key, @stats, :hour)
94
+ key = Redistat::Key.new(@scope, @label, Time.parse("2010-05-14 13:53"))
95
+ Redistat::Summary.update(key, @stats, :hour)
96
+ key = Redistat::Key.new(@scope, @label, Time.parse("2010-05-14 14:32"))
97
+ Redistat::Summary.update(key, @stats, :hour)
98
+ key = Redistat::Key.new(@scope, @label, (last = Time.parse("2010-05-14 15:02")))
99
+ Redistat::Summary.update(key, @stats, :hour)
100
+ [first - 1.hour, last + 1.hour]
101
+ end
102
+
103
+ end
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
data/spec/key_spec.rb ADDED
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Key do
4
+
5
+ before(:each) do
6
+ @scope = "PageViews"
7
+ @label = "about_us"
8
+ @label_hash = Digest::SHA1.hexdigest(@label)
9
+ @date = Time.now
10
+ @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour})
11
+ end
12
+
13
+ it "should initialize properly" do
14
+ @key.scope.should == @scope
15
+ @key.label.should == @label
16
+ @key.label_hash.should == @label_hash
17
+ @key.date.should be_instance_of(Redistat::Date)
18
+ @key.date.to_time.to_s.should == @date.to_s
19
+ end
20
+
21
+ it "should convert to string properly" do
22
+ @key.to_s.should == "#{@scope}/#{@label_hash}:#{@key.date.to_s(:hour)}"
23
+ props = [:year, :month, :day, :hour, :min, :sec]
24
+ props.each do
25
+ @key.to_s(props.last).should == "#{@scope}/#{@label_hash}:#{@key.date.to_s(props.last)}"
26
+ props.pop
27
+ end
28
+ end
29
+
30
+ it "should abide to hash_label option" do
31
+ @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :label_hash => true})
32
+ @key.to_s.should == "#{@scope}/#{@label_hash}:#{@key.date.to_s(:hour)}"
33
+ @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :label_hash => false})
34
+ @key.to_s.should == "#{@scope}/#{@label}:#{@key.date.to_s(:hour)}"
35
+ end
36
+
37
+ it "should have default depth option" do
38
+ @key = Redistat::Key.new(@scope, @label, @date)
39
+ @key.depth.should == :day
40
+ end
41
+
42
+ it "should allow changing attributes" do
43
+ # scope
44
+ @key.scope.should == @scope
45
+ @scope = "VisitorCount"
46
+ @key.scope = @scope
47
+ @key.scope.should == @scope
48
+ # date
49
+ @key.date.to_time.should == @date
50
+ @date = Time.now
51
+ @key.date = @date
52
+ @key.date.to_time.should == @date
53
+ # label
54
+ @key.label.should == @label
55
+ @key.label_hash == @label_hash
56
+ @label = "contact_us"
57
+ @label_hash = Digest::SHA1.hexdigest(@label)
58
+ @key.label = @label
59
+ @key.label.should == @label
60
+ @key.label_hash == @label_hash
61
+ end
62
+
63
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Label do
4
+ include Redistat::Database
5
+
6
+ before(:each) do
7
+ db.flushdb
8
+ @name = "about_us"
9
+ @label = Redistat::Label.new(@name)
10
+ end
11
+
12
+ it "should initialize properly and SHA1 hash the label name" do
13
+ @label.name.should == @name
14
+ @label.hash.should == Digest::SHA1.hexdigest(@name)
15
+ end
16
+
17
+ it "should store a label hash lookup key" do
18
+ @label.save
19
+ @label.saved?.should be_true
20
+ db.get("#{Redistat::KEY_LEBELS}#{@label.hash}").should == @name
21
+
22
+ @name = "contact_us"
23
+ @label = Redistat::Label.create(@name)
24
+ @label.saved?.should be_true
25
+ db.get("#{Redistat::KEY_LEBELS}#{@label.hash}").should == @name
26
+ end
27
+
28
+ end
@@ -0,0 +1,15 @@
1
+ require "redistat"
2
+
3
+ class ModelHelper
4
+ include Redistat::Model
5
+
6
+
7
+ end
8
+
9
+ class ModelHelper2
10
+ include Redistat::Model
11
+
12
+ depth :day
13
+ store_event true
14
+
15
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+ require "model_helper"
3
+
4
+ describe Redistat::Model do
5
+ include Redistat::Database
6
+
7
+ before(:each) do
8
+ db.flushdb
9
+ end
10
+
11
+ it "should should name itself correctly" do
12
+ ModelHelper.send(:name).should == "ModelHelper"
13
+ ModelHelper2.send(:name).should == "ModelHelper2"
14
+ end
15
+
16
+ it "should listen to model-defined options" do
17
+ ModelHelper2.depth.should == :day
18
+ ModelHelper2.store_event.should == true
19
+
20
+ ModelHelper.depth.should == nil
21
+ ModelHelper.store_event.should == nil
22
+ ModelHelper.depth(:hour)
23
+ ModelHelper.depth.should == :hour
24
+ ModelHelper.store_event(true)
25
+ ModelHelper.store_event.should == true
26
+ ModelHelper.options[:depth] = nil
27
+ ModelHelper.options[:store_event] = nil
28
+ ModelHelper.depth.should == nil
29
+ ModelHelper.store_event.should == nil
30
+ end
31
+
32
+ it "should store and fetch stats" do
33
+ ModelHelper.store("sheep.black", {:count => 6, :weight => 461}, 4.hours.ago)
34
+ ModelHelper.store("sheep.black", {:count => 2, :weight => 156})
35
+
36
+ stats = ModelHelper.fetch("sheep.black", 2.hours.ago, 1.hour.from_now)
37
+ stats.total["count"].should == 2
38
+ stats.total["weight"].should == 156
39
+ stats.first.should == stats.total
40
+
41
+ stats = ModelHelper.fetch("sheep.black", 5.hours.ago, 1.hour.from_now)
42
+ stats.total[:count].should == 8
43
+ stats.total[:weight].should == 617
44
+ stats.first.should == stats.total
45
+
46
+ ModelHelper.store("sheep.white", {:count => 5, :weight => 393}, 4.hours.ago)
47
+ ModelHelper.store("sheep.white", {:count => 4, :weight => 316})
48
+
49
+ stats = ModelHelper.fetch("sheep.white", 2.hours.ago, 1.hour.from_now)
50
+ stats.total[:count].should == 4
51
+ stats.total[:weight].should == 316
52
+ stats.first.should == stats.total
53
+
54
+ stats = ModelHelper.fetch("sheep.white", 5.hours.ago, 1.hour.from_now)
55
+ stats.total[:count].should == 9
56
+ stats.total[:weight].should == 709
57
+ stats.first.should == stats.total
58
+ end
59
+
60
+ end
@@ -0,0 +1,9 @@
1
+ daemonize yes
2
+ dir ./spec/db
3
+ pidfile ./redis.pid
4
+ port 8379
5
+ bind 127.0.0.1
6
+ timeout 300
7
+ loglevel debug
8
+ logfile stdout
9
+ databases 16
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Result do
4
+
5
+ it "should should initialize properly" do
6
+ options = {:from => "from", :till => "till"}
7
+ result = Redistat::Result.new(options)
8
+ result.from.should == "from"
9
+ result.till.should == "till"
10
+ end
11
+
12
+ it "should have set_or_incr method" do
13
+ result = Redistat::Result.new
14
+ result[:world].should be_nil
15
+ result.set_or_incr(:world, 3)
16
+ result[:world].should == 3
17
+ result.set_or_incr(:world, 8)
18
+ result[:world].should == 11
19
+ end
20
+
21
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Scope do
4
+ include Redistat::Database
5
+
6
+ before(:all) do
7
+ db.flushdb
8
+ end
9
+
10
+ before(:each) do
11
+ @name = "PageViews"
12
+ @scope = Redistat::Scope.new(@name)
13
+ end
14
+
15
+ it "should initialize properly" do
16
+ @scope.to_s.should == @name
17
+ end
18
+
19
+ it "should increment next_id" do
20
+ scope = Redistat::Scope.new("Visitors")
21
+ @scope.next_id.should == 1
22
+ scope.next_id.should == 1
23
+ @scope.next_id.should == 2
24
+ scope.next_id.should == 2
25
+ end
26
+
27
+ end
@@ -0,0 +1,12 @@
1
+ # add project-relative load paths
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ # require stuff
6
+ require 'redistat'
7
+ require 'rspec'
8
+ require 'rspec/autorun'
9
+
10
+ # use the test Redistat instance
11
+ Redistat.connect({:port => 8379, :db => 15})
12
+ Redistat.flush
@@ -0,0 +1,72 @@
1
+ require "spec_helper"
2
+
3
+ describe Redistat::Summary do
4
+ include Redistat::Database
5
+
6
+ before(:each) do
7
+ db.flushdb
8
+ @scope = "PageViews"
9
+ @label = "about_us"
10
+ @date = Time.now
11
+ @key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
12
+ @stats = {"views" => 3, "visitors" => 2}
13
+ end
14
+
15
+ it "should update a single summary properly" do
16
+ Redistat::Summary.update(@key, @stats, :hour)
17
+ summary = db.hgetall(@key.to_s(:hour))
18
+ summary.should have(2).items
19
+ summary["views"].should == "3"
20
+ summary["visitors"].should == "2"
21
+
22
+ Redistat::Summary.update(@key, @stats, :hour)
23
+ summary = db.hgetall(@key.to_s(:hour))
24
+ summary.should have(2).items
25
+ summary["views"].should == "6"
26
+ summary["visitors"].should == "4"
27
+
28
+ Redistat::Summary.update(@key, {"views" => -4, "visitors" => -3}, :hour)
29
+ summary = db.hgetall(@key.to_s(:hour))
30
+ summary.should have(2).items
31
+ summary["views"].should == "2"
32
+ summary["visitors"].should == "1"
33
+ end
34
+
35
+ it "should update all summaries properly" do
36
+ Redistat::Summary.update_all(@key, @stats, :sec)
37
+ [:year, :month, :day, :hour, :min, :sec, :usec].each do |depth|
38
+ summary = db.hgetall(@key.to_s(depth))
39
+ if depth != :usec
40
+ summary.should have(2).items
41
+ summary["views"].should == "3"
42
+ summary["visitors"].should == "2"
43
+ else
44
+ summary.should have(0).items
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redistat
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jim Myhrberg
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-22 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 2
32
+ - 3
33
+ - 0
34
+ version: 2.3.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: json
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 23
46
+ segments:
47
+ - 1
48
+ - 0
49
+ - 0
50
+ version: 1.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: redis
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 15
62
+ segments:
63
+ - 2
64
+ - 0
65
+ - 0
66
+ version: 2.0.0
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: time_ext
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 27
78
+ segments:
79
+ - 0
80
+ - 2
81
+ - 6
82
+ version: 0.2.6
83
+ type: :runtime
84
+ version_requirements: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ name: rspec
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 13
94
+ segments:
95
+ - 2
96
+ - 0
97
+ - 1
98
+ version: 2.0.1
99
+ type: :development
100
+ version_requirements: *id005
101
+ - !ruby/object:Gem::Dependency
102
+ name: yard
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 5
110
+ segments:
111
+ - 0
112
+ - 6
113
+ - 1
114
+ version: 0.6.1
115
+ type: :development
116
+ version_requirements: *id006
117
+ description: A Redis-backed statistics storage and querying library written in Ruby.
118
+ email: contact@jimeh.me
119
+ executables: []
120
+
121
+ extensions: []
122
+
123
+ extra_rdoc_files:
124
+ - LICENSE
125
+ - README.md
126
+ files:
127
+ - .document
128
+ - .gitignore
129
+ - .rspec
130
+ - Gemfile
131
+ - Gemfile.lock
132
+ - LICENSE
133
+ - README.md
134
+ - Rakefile
135
+ - VERSION
136
+ - lib/redistat.rb
137
+ - lib/redistat/collection.rb
138
+ - lib/redistat/core_ext/date.rb
139
+ - lib/redistat/core_ext/fixnum.rb
140
+ - lib/redistat/core_ext/time.rb
141
+ - lib/redistat/database.rb
142
+ - lib/redistat/date.rb
143
+ - lib/redistat/event.rb
144
+ - lib/redistat/finder.rb
145
+ - lib/redistat/finder/date_set.rb
146
+ - lib/redistat/key.rb
147
+ - lib/redistat/label.rb
148
+ - lib/redistat/model.rb
149
+ - lib/redistat/result.rb
150
+ - lib/redistat/scope.rb
151
+ - lib/redistat/summary.rb
152
+ - spec/_redistat_spec.rb
153
+ - spec/collection_spec.rb
154
+ - spec/date_spec.rb
155
+ - spec/db/.emptydir
156
+ - spec/event_spec.rb
157
+ - spec/finder/date_set_spec.rb
158
+ - spec/finder_spec.rb
159
+ - spec/key_spec.rb
160
+ - spec/label_spec.rb
161
+ - spec/model_helper.rb
162
+ - spec/model_spec.rb
163
+ - spec/redis-test.conf
164
+ - spec/result_spec.rb
165
+ - spec/scope_spec.rb
166
+ - spec/spec_helper.rb
167
+ - spec/summary_spec.rb
168
+ has_rdoc: true
169
+ homepage: http://github.com/jimeh/redistat
170
+ licenses: []
171
+
172
+ post_install_message:
173
+ rdoc_options:
174
+ - --charset=UTF-8
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ hash: 3
183
+ segments:
184
+ - 0
185
+ version: "0"
186
+ required_rubygems_version: !ruby/object:Gem::Requirement
187
+ none: false
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ hash: 3
192
+ segments:
193
+ - 0
194
+ version: "0"
195
+ requirements: []
196
+
197
+ rubyforge_project:
198
+ rubygems_version: 1.3.7
199
+ signing_key:
200
+ specification_version: 3
201
+ summary: A Redis-backed statistics storage and querying library written in Ruby.
202
+ test_files:
203
+ - spec/_redistat_spec.rb
204
+ - spec/collection_spec.rb
205
+ - spec/date_spec.rb
206
+ - spec/event_spec.rb
207
+ - spec/finder/date_set_spec.rb
208
+ - spec/finder_spec.rb
209
+ - spec/key_spec.rb
210
+ - spec/label_spec.rb
211
+ - spec/model_helper.rb
212
+ - spec/model_spec.rb
213
+ - spec/result_spec.rb
214
+ - spec/scope_spec.rb
215
+ - spec/spec_helper.rb
216
+ - spec/summary_spec.rb