tabs 0.6.1 → 0.6.2
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 +6 -5
- data/lib/tabs/metrics/counter.rb +5 -1
- data/lib/tabs/metrics/task.rb +4 -0
- data/lib/tabs/metrics/value.rb +4 -0
- data/lib/tabs/storage.rb +7 -0
- data/lib/tabs/tabs.rb +2 -6
- data/lib/tabs/version.rb +1 -1
- data/spec/lib/tabs/metrics/counter_spec.rb +31 -0
- data/spec/lib/tabs/metrics/value_spec.rb +26 -0
- data/spec/lib/tabs_spec.rb +18 -7
- metadata +23 -5
- checksums.yaml +0 -15
data/README.md
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
|
3
3
|
# Tabs
|
4
4
|
|
5
|
-
Tabs is a redis-backed metrics tracker that supports counts, sums,
|
5
|
+
Tabs is a redis-backed metrics tracker that supports counts, sums,
|
6
|
+
averages, and min/max, and task based stats sliceable by the minute, hour, day, week, month, and year.
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
9
10
|
Add this line to your application's Gemfile:
|
10
11
|
|
11
|
-
gem 'tabs'
|
12
|
+
gem 'tabs', '~> 0.6.1'
|
12
13
|
|
13
14
|
And then execute:
|
14
15
|
|
@@ -28,7 +29,7 @@ type will only be available in v0.6.0 and above.
|
|
28
29
|
|
29
30
|
## Usage
|
30
31
|
|
31
|
-
Metrics come in
|
32
|
+
Metrics come in three flavors: counters, values, and tasks.
|
32
33
|
|
33
34
|
### Counter Metrics
|
34
35
|
|
@@ -129,7 +130,7 @@ Tabs.complete_task("mobile-to-purchase", "2g4hj17787s")
|
|
129
130
|
Retrieving stats for a task metric is just like the other types:
|
130
131
|
|
131
132
|
```ruby
|
132
|
-
Tabs.get_stats("mobile-to-purchase", (Time.now - 6.hours)..Time.now), :
|
133
|
+
Tabs.get_stats("mobile-to-purchase", (Time.now - 6.hours)..Time.now), :minute)
|
133
134
|
```
|
134
135
|
|
135
136
|
This will return a hash like this:
|
@@ -139,7 +140,7 @@ This will return a hash like this:
|
|
139
140
|
started: 3, #=> number of items started within the period
|
140
141
|
completed: 2, #=> number of items completed within the period
|
141
142
|
completed_within_period: 2, #=> number started AND completed within the period
|
142
|
-
completion_rate: 0.18, #=> rate of completion
|
143
|
+
completion_rate: 0.18, #=> rate of completion in the specified resolution (e.g. :minute)
|
143
144
|
average_completion_time: 1.5 #=> average completion time in the specified resolution
|
144
145
|
}
|
145
146
|
```
|
data/lib/tabs/metrics/counter.rb
CHANGED
data/lib/tabs/metrics/task.rb
CHANGED
data/lib/tabs/metrics/value.rb
CHANGED
data/lib/tabs/storage.rb
CHANGED
@@ -24,10 +24,17 @@ module Tabs
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def del(*keys)
|
27
|
+
return 0 if keys.empty?
|
27
28
|
prefixed_keys = keys.map { |k| "tabs:#{k}" }
|
28
29
|
redis.del(*prefixed_keys)
|
29
30
|
end
|
30
31
|
|
32
|
+
def del_by_prefix(pattern)
|
33
|
+
keys = redis.keys("tabs:#{pattern}*")
|
34
|
+
return 0 if keys.empty?
|
35
|
+
redis.del(*keys)
|
36
|
+
end
|
37
|
+
|
31
38
|
def incr(key)
|
32
39
|
redis.incr("tabs:#{key}")
|
33
40
|
end
|
data/lib/tabs/tabs.rb
CHANGED
@@ -86,13 +86,9 @@ module Tabs
|
|
86
86
|
|
87
87
|
def drop_metric(key)
|
88
88
|
raise UnknownMetricError.new("Unknown metric: #{key}") unless metric_exists?(key)
|
89
|
+
metric = get_metric(key)
|
90
|
+
metric.drop!
|
89
91
|
hdel "metrics", key
|
90
|
-
Tabs::RESOLUTIONS.each do |resolution|
|
91
|
-
stat_key = "stat:keys:#{key}:#{resolution}"
|
92
|
-
keys = smembers(stat_key)
|
93
|
-
del(keys)
|
94
|
-
del stat_key
|
95
|
-
end
|
96
92
|
end
|
97
93
|
|
98
94
|
private
|
data/lib/tabs/version.rb
CHANGED
@@ -2,6 +2,8 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Tabs::Metrics::Counter do
|
4
4
|
|
5
|
+
include Tabs::Storage
|
6
|
+
|
5
7
|
let(:metric) { Tabs.create_metric("foo", "counter") }
|
6
8
|
let(:now) { Time.utc(2000, 1, 1, 0, 0) }
|
7
9
|
|
@@ -111,4 +113,33 @@ describe Tabs::Metrics::Counter do
|
|
111
113
|
|
112
114
|
end
|
113
115
|
|
116
|
+
describe ".drop!" do
|
117
|
+
|
118
|
+
before do
|
119
|
+
3.times { metric.increment }
|
120
|
+
expect(exists("stat:counter:foo:total")).to be_true
|
121
|
+
@count_keys = (Tabs::RESOLUTIONS.map do |res|
|
122
|
+
smembers("stat:counter:foo:keys:#{res}")
|
123
|
+
end).flatten
|
124
|
+
metric.drop!
|
125
|
+
end
|
126
|
+
|
127
|
+
it "deletes the counter total key" do
|
128
|
+
expect(exists("stat:counter:foo:total")).to be_false
|
129
|
+
end
|
130
|
+
|
131
|
+
it "deletes all resolution count keys" do
|
132
|
+
@count_keys.each do |key|
|
133
|
+
expect(exists(key)).to be_false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it "deletes all resolution key collection keys" do
|
138
|
+
Tabs::RESOLUTIONS.each do |res|
|
139
|
+
expect(exists("stat:counter:foo:keys:#{res}")).to be_false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
114
145
|
end
|
@@ -2,6 +2,8 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Tabs::Metrics::Value do
|
4
4
|
|
5
|
+
include Tabs::Storage
|
6
|
+
|
5
7
|
let(:metric) { Tabs.create_metric("foo", "value") }
|
6
8
|
let(:now) { Time.utc(2000, 1, 1, 0, 0) }
|
7
9
|
|
@@ -82,4 +84,28 @@ describe Tabs::Metrics::Value do
|
|
82
84
|
|
83
85
|
end
|
84
86
|
|
87
|
+
describe ".drop!" do
|
88
|
+
|
89
|
+
before do
|
90
|
+
3.times { metric.record(rand(30)) }
|
91
|
+
@count_keys = (Tabs::RESOLUTIONS.map do |res|
|
92
|
+
smembers("stat:value:foo:keys:#{res}")
|
93
|
+
end).flatten
|
94
|
+
metric.drop!
|
95
|
+
end
|
96
|
+
|
97
|
+
it "deletes all resolution count keys" do
|
98
|
+
@count_keys.each do |key|
|
99
|
+
expect(exists(key)).to be_false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "deletes all resolution key collection keys" do
|
104
|
+
Tabs::RESOLUTIONS.each do |res|
|
105
|
+
expect(exists("stat:value:foo:keys:#{res}")).to be_false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
85
111
|
end
|
data/spec/lib/tabs_spec.rb
CHANGED
@@ -74,15 +74,18 @@ describe Tabs do
|
|
74
74
|
it "removes the metric from the list_metrics" do
|
75
75
|
Tabs.drop_metric("foo")
|
76
76
|
expect(Tabs.list_metrics).to_not include("foo")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "results in metric_exists? returning false" do
|
80
|
+
Tabs.drop_metric("foo")
|
77
81
|
expect(Tabs.metric_exists?("foo")).to be_false
|
78
82
|
end
|
79
83
|
|
80
|
-
it "
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
+
it "calls drop! on the metric" do
|
85
|
+
metric = stub(:metric)
|
86
|
+
Tabs.stub(get_metric: metric)
|
87
|
+
metric.should_receive(:drop!)
|
84
88
|
Tabs.drop_metric("foo")
|
85
|
-
expect(redis.keys).to_not include(keys[0])
|
86
89
|
end
|
87
90
|
|
88
91
|
end
|
@@ -144,13 +147,21 @@ describe Tabs do
|
|
144
147
|
|
145
148
|
describe "#metric_type" do
|
146
149
|
|
147
|
-
it "returns the type of a
|
150
|
+
it "returns the type of a counter metric" do
|
148
151
|
Tabs.create_metric("foo", "counter")
|
149
|
-
Tabs.create_metric("bar", "value")
|
150
152
|
expect(Tabs.metric_type("foo")).to eq("counter")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "returns the type of a value metric" do
|
156
|
+
Tabs.create_metric("bar", "value")
|
151
157
|
expect(Tabs.metric_type("bar")).to eq("value")
|
152
158
|
end
|
153
159
|
|
160
|
+
it "returns the type of a task metric" do
|
161
|
+
Tabs.create_metric("baz", "task")
|
162
|
+
expect(Tabs.metric_type("baz")).to eq("task")
|
163
|
+
end
|
164
|
+
|
154
165
|
end
|
155
166
|
|
156
167
|
end
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- JC Grubbs
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-24 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: activesupport
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: json
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: redis
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -55,6 +62,7 @@ dependencies:
|
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: fakeredis
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ! '>='
|
60
68
|
- !ruby/object:Gem::Version
|
@@ -62,6 +70,7 @@ dependencies:
|
|
62
70
|
type: :development
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ! '>='
|
67
76
|
- !ruby/object:Gem::Version
|
@@ -69,6 +78,7 @@ dependencies:
|
|
69
78
|
- !ruby/object:Gem::Dependency
|
70
79
|
name: pry
|
71
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
72
82
|
requirements:
|
73
83
|
- - ! '>='
|
74
84
|
- !ruby/object:Gem::Version
|
@@ -76,6 +86,7 @@ dependencies:
|
|
76
86
|
type: :development
|
77
87
|
prerelease: false
|
78
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
79
90
|
requirements:
|
80
91
|
- - ! '>='
|
81
92
|
- !ruby/object:Gem::Version
|
@@ -83,6 +94,7 @@ dependencies:
|
|
83
94
|
- !ruby/object:Gem::Dependency
|
84
95
|
name: rake
|
85
96
|
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
86
98
|
requirements:
|
87
99
|
- - ! '>='
|
88
100
|
- !ruby/object:Gem::Version
|
@@ -90,6 +102,7 @@ dependencies:
|
|
90
102
|
type: :development
|
91
103
|
prerelease: false
|
92
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
93
106
|
requirements:
|
94
107
|
- - ! '>='
|
95
108
|
- !ruby/object:Gem::Version
|
@@ -97,6 +110,7 @@ dependencies:
|
|
97
110
|
- !ruby/object:Gem::Dependency
|
98
111
|
name: rspec
|
99
112
|
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
100
114
|
requirements:
|
101
115
|
- - ! '>='
|
102
116
|
- !ruby/object:Gem::Version
|
@@ -104,6 +118,7 @@ dependencies:
|
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
107
122
|
requirements:
|
108
123
|
- - ! '>='
|
109
124
|
- !ruby/object:Gem::Version
|
@@ -111,6 +126,7 @@ dependencies:
|
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
127
|
name: timecop
|
113
128
|
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
114
130
|
requirements:
|
115
131
|
- - ! '>='
|
116
132
|
- !ruby/object:Gem::Version
|
@@ -118,6 +134,7 @@ dependencies:
|
|
118
134
|
type: :development
|
119
135
|
prerelease: false
|
120
136
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
121
138
|
requirements:
|
122
139
|
- - ! '>='
|
123
140
|
- !ruby/object:Gem::Version
|
@@ -162,7 +179,6 @@ files:
|
|
162
179
|
- tabs.gemspec
|
163
180
|
homepage: https://github.com/thegrubbsian/tabs
|
164
181
|
licenses: []
|
165
|
-
metadata: {}
|
166
182
|
post_install_message: ! '**** NOTICE ****
|
167
183
|
|
168
184
|
Please note there are breaking changes in this version of tabs!
|
@@ -176,20 +192,22 @@ rdoc_options: []
|
|
176
192
|
require_paths:
|
177
193
|
- lib
|
178
194
|
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
none: false
|
179
196
|
requirements:
|
180
197
|
- - ! '>='
|
181
198
|
- !ruby/object:Gem::Version
|
182
199
|
version: '0'
|
183
200
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
184
202
|
requirements:
|
185
203
|
- - ! '>='
|
186
204
|
- !ruby/object:Gem::Version
|
187
205
|
version: '0'
|
188
206
|
requirements: []
|
189
207
|
rubyforge_project:
|
190
|
-
rubygems_version:
|
208
|
+
rubygems_version: 1.8.23
|
191
209
|
signing_key:
|
192
|
-
specification_version:
|
210
|
+
specification_version: 3
|
193
211
|
summary: A redis-backed metrics tracker for keeping tabs on pretty much anything ;)
|
194
212
|
test_files:
|
195
213
|
- spec/lib/tabs/metrics/counter_spec.rb
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
ZGVkZDU2ZjE2NzVjMDFiNjRjZDVmZWQyODQzNmE0MzZmMWE3MzRkZA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZThhYTI3ODI5ZGNhM2M5ZmU2MWE4YTg0YzljOTQ3NDIyNDg1Njc4YQ==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MDJjNzY3YzM5MTAyYmJkOWUyYWMwYmNhYmU0YWY2YjcwYWJmMjQ2ZWRiZGZj
|
10
|
-
MDU0MjU2MzJiMTE5NzNlMDcwMzY0YmI2MTJmNzg5YzdmMmIyMjdkMjg5NjAz
|
11
|
-
ZDJiMjExMjNhNGI2YjY3MWJmNjg0ODJjODk3Mjc0ZjJhM2QxYjc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
M2U3MDczNmZhNjJhYzE5MDA2NzlkMzliYjQ0MzBmOWUxNmVmNDU0Zjc0MWRk
|
14
|
-
ZWNiNDVmOTEzNDdjMzQ3YWRlMzRkNGI2ZTk3MWYyNmYwYTk5MjMyYzVkNDQ3
|
15
|
-
OTRlZjA1ZTIzYzY0ZjQ5ZTljNjQ2MGZiYTkwMTkwYmVhNzZmMDg=
|