tabs 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -0
- data/lib/tabs/helpers.rb +5 -0
- data/lib/tabs/metrics/value.rb +22 -21
- data/lib/tabs/storage.rb +8 -0
- data/lib/tabs/version.rb +1 -1
- data/spec/lib/tabs/metrics/value_spec.rb +7 -7
- data/tabs.gemspec +18 -4
- metadata +33 -6
data/README.md
CHANGED
@@ -276,6 +276,20 @@ enumerable and most existing code utilizing tabs should continue to
|
|
276
276
|
function. However, please review the docs for more information if you
|
277
277
|
encounter issues when upgrading.
|
278
278
|
|
279
|
+
### Breaking Changes in v0.8.2
|
280
|
+
|
281
|
+
In version 0.8.2 and higher the storage keys for value metrics have been
|
282
|
+
changed. Originally the various pieces (avg, sum, count, etc) were
|
283
|
+
stored in a JSON serialized string in a single key. The intent was that
|
284
|
+
this would comprise a poor-mans transaction of sorts. The downside
|
285
|
+
however was a major hit on performance when doing a lot of writes or
|
286
|
+
reading stats for a large date range. In v0.8.2 these component values
|
287
|
+
are stored in a real Redis hash and updated atomically when a value is
|
288
|
+
recorded. In future versions this will be changed to use a MULTI
|
289
|
+
statement to simulate a transaction. Value data that was recorded prior
|
290
|
+
to v0.8.2 will not be accessible in this or future versions so please
|
291
|
+
continue to use v0.8.1 or lower if that is an issue.
|
292
|
+
|
279
293
|
## Contributing
|
280
294
|
|
281
295
|
1. Fork it
|
data/lib/tabs/helpers.rb
CHANGED
data/lib/tabs/metrics/value.rb
CHANGED
@@ -23,11 +23,13 @@ module Tabs
|
|
23
23
|
def stats(period, resolution)
|
24
24
|
timestamps = timestamp_range period, resolution
|
25
25
|
keys = timestamps.map do |ts|
|
26
|
-
|
26
|
+
formatted_time = Tabs::Resolution.serialize(resolution, ts)
|
27
|
+
"stat:value:#{key}:data:#{formatted_time}"
|
27
28
|
end
|
28
29
|
|
29
30
|
values = mget(*keys).map do |v|
|
30
|
-
value = v.nil? ? default_value(0) :
|
31
|
+
value = v.nil? ? default_value(0) : v
|
32
|
+
value = Hash[value.map { |k, i| [k, to_numeric(i)] }]
|
31
33
|
value["timestamp"] = timestamps.shift
|
32
34
|
value.with_indifferent_access
|
33
35
|
end
|
@@ -42,35 +44,34 @@ module Tabs
|
|
42
44
|
private
|
43
45
|
|
44
46
|
def update_values(stat_key, value)
|
45
|
-
|
46
|
-
|
47
|
-
update_min(
|
48
|
-
update_max(
|
49
|
-
update_avg(
|
50
|
-
set(stat_key, JSON.generate(hash))
|
47
|
+
count = update_count(stat_key)
|
48
|
+
sum = update_sum(stat_key, value)
|
49
|
+
update_min(stat_key, value)
|
50
|
+
update_max(stat_key, value)
|
51
|
+
update_avg(stat_key, sum, count)
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
-
|
55
|
-
return JSON.parse(hash) if hash
|
56
|
-
default_value
|
54
|
+
def update_count(stat_key)
|
55
|
+
hincrby(stat_key, "count", 1)
|
57
56
|
end
|
58
57
|
|
59
|
-
def
|
60
|
-
|
61
|
-
hash["sum"] += value
|
58
|
+
def update_sum(stat_key, value)
|
59
|
+
hincrby(stat_key, "sum", value)
|
62
60
|
end
|
63
61
|
|
64
|
-
def update_min(
|
65
|
-
|
62
|
+
def update_min(stat_key, value)
|
63
|
+
min = (hget(stat_key, "min") || 0).to_i
|
64
|
+
hset(stat_key, "min", value) if value < min || min == 0
|
66
65
|
end
|
67
66
|
|
68
|
-
def update_max(
|
69
|
-
|
67
|
+
def update_max(stat_key, value)
|
68
|
+
max = (hget(stat_key, "max") || 0).to_i
|
69
|
+
hset(stat_key, "max", value) if value > max || max == 0
|
70
70
|
end
|
71
71
|
|
72
|
-
def update_avg(
|
73
|
-
|
72
|
+
def update_avg(stat_key, sum, count)
|
73
|
+
avg = sum.to_f / count.to_f
|
74
|
+
hset(stat_key, "avg", avg)
|
74
75
|
end
|
75
76
|
|
76
77
|
def default_value(nil_value=nil)
|
data/lib/tabs/storage.rb
CHANGED
data/lib/tabs/version.rb
CHANGED
@@ -16,7 +16,7 @@ describe Tabs::Metrics::Value do
|
|
16
16
|
metric.record(42)
|
17
17
|
time = Time.utc(now.year, now.month, now.day, now.hour)
|
18
18
|
stats = metric.stats(((now - 2.hours)..(now + 4.hours)), :hour)
|
19
|
-
expect(stats).to include({ "timestamp"=>time, "count"=>2, "min"=>17, "max"=>42, "sum"=>59, "avg"=>29})
|
19
|
+
expect(stats).to include({ "timestamp"=>time, "count"=>2, "min"=>17, "max"=>42, "sum"=>59, "avg"=>29.5})
|
20
20
|
end
|
21
21
|
|
22
22
|
it "applys the value to the specified timestamp if one is supplied" do
|
@@ -58,42 +58,42 @@ describe Tabs::Metrics::Value do
|
|
58
58
|
create_span(:minutes)
|
59
59
|
stats = metric.stats(now..(now + 7.minutes), :minute)
|
60
60
|
expect(stats).to include({ "timestamp" => (now + 3.minutes), "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
61
|
-
expect(stats).to include({ "timestamp" => (now + 6.minutes), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
61
|
+
expect(stats).to include({ "timestamp" => (now + 6.minutes), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
62
62
|
end
|
63
63
|
|
64
64
|
it "returns the expected results for an hourly metric" do
|
65
65
|
create_span(:hours)
|
66
66
|
stats = metric.stats(now..(now + 7.hours), :hour)
|
67
67
|
expect(stats).to include({ "timestamp" => (now + 3.hours), "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
68
|
-
expect(stats).to include({ "timestamp" => (now + 6.hours), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
68
|
+
expect(stats).to include({ "timestamp" => (now + 6.hours), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
69
69
|
end
|
70
70
|
|
71
71
|
it "returns the expected results for a daily metric" do
|
72
72
|
create_span(:days)
|
73
73
|
stats = metric.stats(now..(now + 7.days), :day)
|
74
74
|
expect(stats).to include({ "timestamp" => (now + 3.days), "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
75
|
-
expect(stats).to include({ "timestamp" => (now + 6.days), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
75
|
+
expect(stats).to include({ "timestamp" => (now + 6.days), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
76
76
|
end
|
77
77
|
|
78
78
|
it "returns the expected results for a weekly metric" do
|
79
79
|
create_span(:weeks)
|
80
80
|
stats = metric.stats(now..(now + 7.weeks), :week)
|
81
81
|
expect(stats).to include({ "timestamp" => (now + 3.weeks).beginning_of_week, "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
82
|
-
expect(stats).to include({ "timestamp" => (now + 6.weeks).beginning_of_week, "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
82
|
+
expect(stats).to include({ "timestamp" => (now + 6.weeks).beginning_of_week, "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
83
83
|
end
|
84
84
|
|
85
85
|
it "returns the expected results for a monthly metric" do
|
86
86
|
create_span(:months)
|
87
87
|
stats = metric.stats(now..(now + 7.months), :month)
|
88
88
|
expect(stats).to include({ "timestamp" => (now + 3.months), "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
89
|
-
expect(stats).to include({ "timestamp" => (now + 6.months), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
89
|
+
expect(stats).to include({ "timestamp" => (now + 6.months), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
90
90
|
end
|
91
91
|
|
92
92
|
it "returns the expected results for a yearly metric" do
|
93
93
|
create_span(:years)
|
94
94
|
stats = metric.stats(now..(now + 7.years), :year)
|
95
95
|
expect(stats).to include({ "timestamp" => (now + 3.years), "count"=>1, "min"=>10, "max"=>10, "sum"=>10, "avg"=>10})
|
96
|
-
expect(stats).to include({ "timestamp" => (now + 6.years), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17})
|
96
|
+
expect(stats).to include({ "timestamp" => (now + 6.years), "count"=>2, "min"=>15, "max"=>20, "sum"=>35, "avg"=>17.5})
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
data/tabs.gemspec
CHANGED
@@ -20,11 +20,25 @@ Gem::Specification.new do |gem|
|
|
20
20
|
|
21
21
|
gem.post_install_message = <<EOS
|
22
22
|
Tabs v0.8.0 - BREAKING CHANGES:
|
23
|
-
|
24
|
-
an array of hashes.
|
25
|
-
|
26
|
-
|
23
|
+
In version 0.8.0 and higher the get_stats method returns a more robust
|
24
|
+
object instead of just an array of hashes. These stats objects are
|
25
|
+
enumerable and most existing code utilizing tabs should continue to
|
26
|
+
function. However, please review the docs for more information if you
|
27
|
+
encounter issues when upgrading. Please review the README if installing
|
27
28
|
v0.8.0 or higher.
|
29
|
+
|
30
|
+
Tabs v0.8.2 - BREAKING CHANGES:
|
31
|
+
In version 0.8.2 and higher the storage keys for value metrics have been
|
32
|
+
changed. Originally the various pieces (avg, sum, count, etc) were
|
33
|
+
stored in a JSON serialized string in a single key. The intent was that
|
34
|
+
this would comprise a poor-mans transaction of sorts. The downside
|
35
|
+
however was a major hit on performance when doing a lot of writes or
|
36
|
+
reading stats for a large date range. In v0.8.2 these component values
|
37
|
+
are stored in a real Redis hash and updated atomically when a value is
|
38
|
+
recorded. In future versions this will be changed to use a MULTI
|
39
|
+
statement to simulate a transaction. Value data that was recorded prior
|
40
|
+
to v0.8.2 will not be accessible in this or future versions so please
|
41
|
+
continue to use v0.8.1 or lower if that is an issue.
|
28
42
|
EOS
|
29
43
|
|
30
44
|
gem.add_dependency "activesupport", ">= 3.2"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -186,16 +186,43 @@ homepage: https://github.com/thegrubbsian/tabs
|
|
186
186
|
licenses: []
|
187
187
|
post_install_message: ! 'Tabs v0.8.0 - BREAKING CHANGES:
|
188
188
|
|
189
|
-
|
189
|
+
In version 0.8.0 and higher the get_stats method returns a more robust
|
190
190
|
|
191
|
-
an array of hashes.
|
191
|
+
object instead of just an array of hashes. These stats objects are
|
192
192
|
|
193
|
-
|
193
|
+
enumerable and most existing code utilizing tabs should continue to
|
194
194
|
|
195
|
-
|
195
|
+
function. However, please review the docs for more information if you
|
196
|
+
|
197
|
+
encounter issues when upgrading. Please review the README if installing
|
196
198
|
|
197
199
|
v0.8.0 or higher.
|
198
200
|
|
201
|
+
|
202
|
+
Tabs v0.8.2 - BREAKING CHANGES:
|
203
|
+
|
204
|
+
In version 0.8.2 and higher the storage keys for value metrics have been
|
205
|
+
|
206
|
+
changed. Originally the various pieces (avg, sum, count, etc) were
|
207
|
+
|
208
|
+
stored in a JSON serialized string in a single key. The intent was that
|
209
|
+
|
210
|
+
this would comprise a poor-mans transaction of sorts. The downside
|
211
|
+
|
212
|
+
however was a major hit on performance when doing a lot of writes or
|
213
|
+
|
214
|
+
reading stats for a large date range. In v0.8.2 these component values
|
215
|
+
|
216
|
+
are stored in a real Redis hash and updated atomically when a value is
|
217
|
+
|
218
|
+
recorded. In future versions this will be changed to use a MULTI
|
219
|
+
|
220
|
+
statement to simulate a transaction. Value data that was recorded prior
|
221
|
+
|
222
|
+
to v0.8.2 will not be accessible in this or future versions so please
|
223
|
+
|
224
|
+
continue to use v0.8.1 or lower if that is an issue.
|
225
|
+
|
199
226
|
'
|
200
227
|
rdoc_options: []
|
201
228
|
require_paths:
|