redistat 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,12 +1,14 @@
1
1
  source 'http://rubygems.org/'
2
2
 
3
3
  gem 'activesupport', '>= 2.3.0'
4
- gem 'json', '>= 1.0.0'
5
- gem 'redis', '>= 2.0.0'
4
+ gem 'json', '>= 1.4.6'
5
+ gem 'redis', '>= 2.1.1'
6
+ gem 'system_timer', '>= 1.0.0'
6
7
  gem 'time_ext', '>= 0.2.6'
7
8
 
8
9
  group :development do
9
- gem 'rspec', '>= 2.0.1'
10
- gem 'yard', '>= 0.6.1'
10
+ gem 'jeweler', '>= 1.5.1'
11
+ gem 'rspec', '>= 2.1.0'
12
+ gem 'yard', '>= 0.6.3'
11
13
  gem 'i18n'
12
14
  end
@@ -3,8 +3,14 @@ GEM
3
3
  specs:
4
4
  activesupport (3.0.3)
5
5
  diff-lcs (1.1.2)
6
+ git (1.2.5)
6
7
  i18n (0.4.2)
8
+ jeweler (1.5.1)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
7
12
  json (1.4.6)
13
+ rake (0.8.7)
8
14
  redis (2.1.1)
9
15
  rspec (2.1.0)
10
16
  rspec-core (~> 2.1.0)
@@ -14,6 +20,7 @@ GEM
14
20
  rspec-expectations (2.1.0)
15
21
  diff-lcs (~> 1.1.2)
16
22
  rspec-mocks (2.1.0)
23
+ system_timer (1.0)
17
24
  time_ext (0.2.6)
18
25
  activesupport (>= 2.3.0)
19
26
  yard (0.6.3)
@@ -24,8 +31,10 @@ PLATFORMS
24
31
  DEPENDENCIES
25
32
  activesupport (>= 2.3.0)
26
33
  i18n
27
- json (>= 1.0.0)
28
- redis (>= 2.0.0)
29
- rspec (>= 2.0.1)
34
+ jeweler (>= 1.5.1)
35
+ json (>= 1.4.6)
36
+ redis (>= 2.1.1)
37
+ rspec (>= 2.1.0)
38
+ system_timer (>= 1.0.0)
30
39
  time_ext (>= 0.2.6)
31
- yard (>= 0.6.1)
40
+ yard (>= 0.6.3)
data/README.md CHANGED
@@ -2,11 +2,66 @@
2
2
 
3
3
  A Redis-backed statistics storage and querying library written in Ruby.
4
4
 
5
- ## Early Beta
5
+ Redistat was originally created to replace a small hacked together statistics collection solution which was MySQL-based. When I started I had a short list of requirements:
6
6
 
7
- Currently this is an early beta release. Readme and documentation is forthcoming.
7
+ * Store and increment/decrement integer values (counters, etc)
8
+ * Up to the second statistics available at all times
9
+ * Screamingly fast
8
10
 
9
- For now, please check `spec/model_spec.rb` and `spec/model_helper.rb` to get started with how to use Redistat.
11
+ Redis fits perfectly with all of these requirements. It has atomic operations like increment, and it's lightning fast, meaning if the data is structured well, the initial stats reporting call will store data in a format that's instantly retrievable just as fast.
12
+
13
+ ## Installation
14
+
15
+ gem install redistat
16
+
17
+ ## Usage
18
+
19
+ The simplest way to use Redistat is through the model wrapper.
20
+
21
+ class VisitorStats
22
+ include Redistat::Model
23
+ end
24
+
25
+ Before any of you Rails-purists start complaining about the model name being plural, I want to point out that it makes sense with Redistat, cause a model doesn't exactly return a specific row or object. But I'm getting ahead of myself.
26
+
27
+ To store statistics we essentially tell Redistat that an event has occurred with a label of X, and statistics of Y. So let's say we want to store a page view event on the `/about` page on a site:
28
+
29
+ VisitorStats.store('/about', {:views => 1})
30
+
31
+ In the above case "`/about`" is the label under which the stats are grouped, and the statistics associated with the event is simply a normal Ruby hash, except all values need to be integers, or Redis' increment calls won't work.
32
+
33
+ To later retrieve statistics, we use the `fetch` method:
34
+
35
+ stats = VisitorStats.fetch('/about', 2.hour.ago, Time.now)
36
+ # stats => [{:views => 1}]
37
+ # stats.total => {:views => 1}
38
+
39
+ The fetch method requires 3 arguments, a label, a start time, and an end time. Fetch returns a `Redistat::Collection` object, which is normal Ruby Array with a couple of added methods, like total shown above.
40
+
41
+ For more detailed usage, please check spec files, and source code till I have time to write up a complete readme.
42
+
43
+
44
+ ## Some Technical Details
45
+
46
+ To give a brief look into how Redistat works internally to store statistics, I'm going to use the examples above. The store method accepts a Ruby Hash with statistics to store. Redistat stores all statistics as hashes in Redis. It stores summaries of the stats for the specific time when it happened and all it's parent time groups (second, minute, hour, day, month, year). The default depth Redistat goes to is hour, unless the `depth` option is passed to `store` or `fetch`.
47
+
48
+ In short, the above call to `store` creates the following keys in Redis:
49
+
50
+ VisitorStats//about:2010
51
+ VisitorStats//about:201011
52
+ VisitorStats//about:20101124
53
+ VisitorStats//about:2010112401
54
+
55
+ Each of these keys in Redis are a hash, containing the sums of each statistic point reported for the time frame the key represents. In this case there's two slashes, cause the label we used was “`/about`”, and the scope (class name when used through the model wrapper) and the label are separated with a slash.
56
+
57
+ When retrieving statistics for a given date range, Redistat figures out how to do the least number of calls to Redis to fetch all relevant data. For example, if you want the sum of stats from the 4th till the last of November, the full month of November would first be fetched, then the first 3 days of November would be fetched and removed from the full month stats.
58
+
59
+
60
+ ## Todo
61
+
62
+ * Proper/complete readme.
63
+ * Documentation.
64
+ * Anything else that becomes apparent after real-world use.
10
65
 
11
66
 
12
67
  ## Note on Patches/Pull Requests
data/Rakefile CHANGED
@@ -11,10 +11,12 @@ begin
11
11
  gem.homepage = 'http://github.com/jimeh/redistat'
12
12
  gem.authors = ['Jim Myhrberg']
13
13
  gem.add_dependency 'activesupport', '>= 2.3.0'
14
- gem.add_dependency 'json', '>= 1.0.0'
15
- gem.add_dependency 'redis', '>= 2.0.0'
14
+ gem.add_dependency 'json', '>= 1.4.6'
15
+ gem.add_dependency 'redis', '>= 2.1.1'
16
+ gem.add_dependency 'system_timer', '>= 1.0.0'
16
17
  gem.add_dependency 'time_ext', '>= 0.2.6'
17
- gem.add_development_dependency 'rspec', '>= 2.0.1'
18
+ gem.add_development_dependency 'jeweler', '>= 1.5.1'
19
+ gem.add_development_dependency 'rspec', '>= 2.1.0'
18
20
  gem.add_development_dependency 'yard', '>= 0.6.1'
19
21
  end
20
22
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -82,23 +82,3 @@ module Redistat
82
82
  module_function :connect, :connection, :flush, :redis, :redis=, :options, :threaded
83
83
 
84
84
  end
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
@@ -18,7 +18,7 @@ module Redistat
18
18
  :till => till
19
19
  }.merge(options.merge(opts)))
20
20
  end
21
- alias :find :fetch
21
+ alias :lookup :fetch
22
22
 
23
23
  def hashed_label(boolean = nil)
24
24
  if !boolean.nil?
File without changes
@@ -101,12 +101,3 @@ describe Redistat::Finder do
101
101
  end
102
102
 
103
103
  end
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
@@ -47,26 +47,3 @@ describe Redistat::Summary do
47
47
  end
48
48
 
49
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 CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redistat
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jim Myhrberg
@@ -15,13 +15,14 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-22 00:00:00 +00:00
18
+ date: 2010-11-24 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: activesupport
23
22
  prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
23
+ type: :runtime
24
+ name: activesupport
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
28
  - - ">="
@@ -32,12 +33,44 @@ dependencies:
32
33
  - 3
33
34
  - 0
34
35
  version: 2.3.0
35
- type: :runtime
36
- version_requirements: *id001
36
+ requirement: *id001
37
37
  - !ruby/object:Gem::Dependency
38
+ prerelease: false
39
+ type: :runtime
38
40
  name: json
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ hash: 11
47
+ segments:
48
+ - 1
49
+ - 4
50
+ - 6
51
+ version: 1.4.6
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ prerelease: false
55
+ type: :runtime
56
+ name: redis
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 9
63
+ segments:
64
+ - 2
65
+ - 1
66
+ - 1
67
+ version: 2.1.1
68
+ requirement: *id003
69
+ - !ruby/object:Gem::Dependency
39
70
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
71
+ type: :runtime
72
+ name: system_timer
73
+ version_requirements: &id004 !ruby/object:Gem::Requirement
41
74
  none: false
42
75
  requirements:
43
76
  - - ">="
@@ -48,28 +81,154 @@ dependencies:
48
81
  - 0
49
82
  - 0
50
83
  version: 1.0.0
84
+ requirement: *id004
85
+ - !ruby/object:Gem::Dependency
86
+ prerelease: false
51
87
  type: :runtime
52
- version_requirements: *id002
88
+ name: time_ext
89
+ version_requirements: &id005 !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 27
95
+ segments:
96
+ - 0
97
+ - 2
98
+ - 6
99
+ version: 0.2.6
100
+ requirement: *id005
53
101
  - !ruby/object:Gem::Dependency
54
- name: redis
55
102
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
103
+ type: :development
104
+ name: jeweler
105
+ version_requirements: &id006 !ruby/object:Gem::Requirement
57
106
  none: false
58
107
  requirements:
59
108
  - - ">="
60
109
  - !ruby/object:Gem::Version
61
- hash: 15
110
+ hash: 1
111
+ segments:
112
+ - 1
113
+ - 5
114
+ - 1
115
+ version: 1.5.1
116
+ requirement: *id006
117
+ - !ruby/object:Gem::Dependency
118
+ prerelease: false
119
+ type: :development
120
+ name: rspec
121
+ version_requirements: &id007 !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 11
62
127
  segments:
63
128
  - 2
129
+ - 1
64
130
  - 0
131
+ version: 2.1.0
132
+ requirement: *id007
133
+ - !ruby/object:Gem::Dependency
134
+ prerelease: false
135
+ type: :development
136
+ name: yard
137
+ version_requirements: &id008 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ hash: 1
143
+ segments:
144
+ - 0
145
+ - 6
146
+ - 3
147
+ version: 0.6.3
148
+ requirement: *id008
149
+ - !ruby/object:Gem::Dependency
150
+ prerelease: false
151
+ type: :development
152
+ name: i18n
153
+ version_requirements: &id009 !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ hash: 3
159
+ segments:
65
160
  - 0
66
- version: 2.0.0
161
+ version: "0"
162
+ requirement: *id009
163
+ - !ruby/object:Gem::Dependency
164
+ prerelease: false
67
165
  type: :runtime
68
- version_requirements: *id003
166
+ name: activesupport
167
+ version_requirements: &id010 !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ hash: 3
173
+ segments:
174
+ - 2
175
+ - 3
176
+ - 0
177
+ version: 2.3.0
178
+ requirement: *id010
179
+ - !ruby/object:Gem::Dependency
180
+ prerelease: false
181
+ type: :runtime
182
+ name: json
183
+ version_requirements: &id011 !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ hash: 11
189
+ segments:
190
+ - 1
191
+ - 4
192
+ - 6
193
+ version: 1.4.6
194
+ requirement: *id011
195
+ - !ruby/object:Gem::Dependency
196
+ prerelease: false
197
+ type: :runtime
198
+ name: redis
199
+ version_requirements: &id012 !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ hash: 9
205
+ segments:
206
+ - 2
207
+ - 1
208
+ - 1
209
+ version: 2.1.1
210
+ requirement: *id012
69
211
  - !ruby/object:Gem::Dependency
70
- name: time_ext
71
212
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
213
+ type: :runtime
214
+ name: system_timer
215
+ version_requirements: &id013 !ruby/object:Gem::Requirement
216
+ none: false
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ hash: 23
221
+ segments:
222
+ - 1
223
+ - 0
224
+ - 0
225
+ version: 1.0.0
226
+ requirement: *id013
227
+ - !ruby/object:Gem::Dependency
228
+ prerelease: false
229
+ type: :runtime
230
+ name: time_ext
231
+ version_requirements: &id014 !ruby/object:Gem::Requirement
73
232
  none: false
74
233
  requirements:
75
234
  - - ">="
@@ -80,28 +239,44 @@ dependencies:
80
239
  - 2
81
240
  - 6
82
241
  version: 0.2.6
83
- type: :runtime
84
- version_requirements: *id004
242
+ requirement: *id014
85
243
  - !ruby/object:Gem::Dependency
86
- name: rspec
87
244
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
245
+ type: :development
246
+ name: jeweler
247
+ version_requirements: &id015 !ruby/object:Gem::Requirement
89
248
  none: false
90
249
  requirements:
91
250
  - - ">="
92
251
  - !ruby/object:Gem::Version
93
- hash: 13
252
+ hash: 1
94
253
  segments:
95
- - 2
96
- - 0
97
254
  - 1
98
- version: 2.0.1
255
+ - 5
256
+ - 1
257
+ version: 1.5.1
258
+ requirement: *id015
259
+ - !ruby/object:Gem::Dependency
260
+ prerelease: false
99
261
  type: :development
100
- version_requirements: *id005
262
+ name: rspec
263
+ version_requirements: &id016 !ruby/object:Gem::Requirement
264
+ none: false
265
+ requirements:
266
+ - - ">="
267
+ - !ruby/object:Gem::Version
268
+ hash: 11
269
+ segments:
270
+ - 2
271
+ - 1
272
+ - 0
273
+ version: 2.1.0
274
+ requirement: *id016
101
275
  - !ruby/object:Gem::Dependency
102
- name: yard
103
276
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
277
+ type: :development
278
+ name: yard
279
+ version_requirements: &id017 !ruby/object:Gem::Requirement
105
280
  none: false
106
281
  requirements:
107
282
  - - ">="
@@ -112,8 +287,7 @@ dependencies:
112
287
  - 6
113
288
  - 1
114
289
  version: 0.6.1
115
- type: :development
116
- version_requirements: *id006
290
+ requirement: *id017
117
291
  description: A Redis-backed statistics storage and querying library written in Ruby.
118
292
  email: contact@jimeh.me
119
293
  executables: []
@@ -125,7 +299,6 @@ extra_rdoc_files:
125
299
  - README.md
126
300
  files:
127
301
  - .document
128
- - .gitignore
129
302
  - .rspec
130
303
  - Gemfile
131
304
  - Gemfile.lock
@@ -170,8 +343,8 @@ homepage: http://github.com/jimeh/redistat
170
343
  licenses: []
171
344
 
172
345
  post_install_message:
173
- rdoc_options:
174
- - --charset=UTF-8
346
+ rdoc_options: []
347
+
175
348
  require_paths:
176
349
  - lib
177
350
  required_ruby_version: !ruby/object:Gem::Requirement
data/.gitignore DELETED
@@ -1,26 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
22
- .bundle/*
23
- .yardoc/*
24
- spec/db/*
25
- doc
26
- redistat.gemspec