running_stat 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +2 -0
- data/lib/running_stat.rb +8 -15
- data/lib/running_stat/lua/push_datum.rb +7 -10
- data/lib/running_stat/lua/variance.rb +6 -6
- data/lib/running_stat/redis_backend.rb +10 -0
- data/lib/running_stat/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 692e627aba71ce44c80b57d406c85dd69f38edfc
|
4
|
+
data.tar.gz: 0caada43394fd224b1e8932958bbe18ed1fd4815
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b173a92b2b32bd8decf100e7c4f4f79b179ff4681839abbb4fcb390db1553d411d9ac552779279ee9d4ac8cef767d133f6780dbce8e8927c8ecb8a8560e8f965
|
7
|
+
data.tar.gz: fe7e30605e41b8e2980fa9760b7f722e33f8bf6f1f7b2dec5a7c56ced7c8dd648e345d4a90ac5b676e624d605582e54b8fdd602c67e10f21e0b0a8d6cd703aee
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
|
+
## [0.1.0] - 2016-01-12
|
6
|
+
### Added
|
7
|
+
- n/a
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- All keys for each metric combined into a single redis hash
|
11
|
+
(this will null out old metrics)
|
12
|
+
|
5
13
|
## [0.0.1] - 2016-01-11
|
6
14
|
### Added
|
7
15
|
- Initial release
|
data/README.md
CHANGED
@@ -8,6 +8,8 @@ RunningStat provides distributed redis-backed data buckets on which various stat
|
|
8
8
|
|
9
9
|
The algorithm used is based on Knuth's TAOCP and is numerically stable; a brief writeup is available on Wikipedia under [Algorithms for calculating online variances](https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm).
|
10
10
|
|
11
|
+
RunningStat supports pretty much all versions of ruby, including MRI 1.8.7, 1.9.3, 2.2, and JRuby 1.7/9k.
|
12
|
+
|
11
13
|
Disclaimer: Because it uses atomic Lua scripting, RunningStat requires redis 2.6+.
|
12
14
|
|
13
15
|
|
data/lib/running_stat.rb
CHANGED
@@ -2,6 +2,7 @@ require 'running_stat/version'
|
|
2
2
|
|
3
3
|
require 'redis'
|
4
4
|
|
5
|
+
require 'running_stat/redis_backend'
|
5
6
|
require 'running_stat/lua/push_datum'
|
6
7
|
require 'running_stat/lua/variance'
|
7
8
|
require 'running_stat/insufficient_data_error'
|
@@ -22,26 +23,26 @@ class RunningStat
|
|
22
23
|
|
23
24
|
# Adds a piece of numerical data to the dataset's stats
|
24
25
|
def push(datum)
|
25
|
-
redis.eval(Lua::PUSH_DATUM, [
|
26
|
+
redis.eval(Lua::PUSH_DATUM, [bucket_key], [Float(datum)])
|
26
27
|
rescue ArgumentError => e
|
27
28
|
raise InvalidDataError.new(e) # datum was non-numerical
|
28
29
|
end
|
29
30
|
|
30
31
|
# Returns the number of data points seen, or 0 if the stat does not exist
|
31
32
|
def cardinality
|
32
|
-
redis.
|
33
|
+
redis.hget(bucket_key, RedisBackend::COUNT_FIELD).to_i
|
33
34
|
end
|
34
35
|
|
35
36
|
# Returns the arithmetic mean of data points seen, or 0.0 if non-existent
|
36
37
|
def mean
|
37
|
-
redis.
|
38
|
+
redis.hget(bucket_key, RedisBackend::MEAN_FIELD).to_f
|
38
39
|
end
|
39
40
|
|
40
41
|
# Returns the sample variance of the dataset so far, or raises
|
41
42
|
# an InsufficientDataError if insufficient data (< 2 datapoints)
|
42
43
|
# has been pushed
|
43
44
|
def variance
|
44
|
-
redis.eval(Lua::VARIANCE, [
|
45
|
+
redis.eval(Lua::VARIANCE, [bucket_key], []).to_f
|
45
46
|
rescue Redis::CommandError => e
|
46
47
|
raise InsufficientDataError.new(e) # only CommandError possible
|
47
48
|
end
|
@@ -55,7 +56,7 @@ class RunningStat
|
|
55
56
|
|
56
57
|
# Resets the stat to reflect an empty dataset
|
57
58
|
def flush
|
58
|
-
redis.del(
|
59
|
+
redis.del(bucket_key)
|
59
60
|
end
|
60
61
|
|
61
62
|
private
|
@@ -64,15 +65,7 @@ class RunningStat
|
|
64
65
|
@redis || Redis.current
|
65
66
|
end
|
66
67
|
|
67
|
-
def
|
68
|
-
"#{BASE_KEY}:#{@data_bucket}
|
69
|
-
end
|
70
|
-
|
71
|
-
def mean_key
|
72
|
-
"#{BASE_KEY}:#{@data_bucket}:mean"
|
73
|
-
end
|
74
|
-
|
75
|
-
def sum_sq_diff_key
|
76
|
-
"#{BASE_KEY}:#{@data_bucket}:sum_sq_diff"
|
68
|
+
def bucket_key
|
69
|
+
"#{BASE_KEY}:#{@data_bucket}"
|
77
70
|
end
|
78
71
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'digest/sha1'
|
2
|
+
require 'running_stat/redis_backend'
|
2
3
|
|
3
4
|
class RunningStat
|
4
5
|
module Lua
|
5
6
|
# Keys:
|
6
|
-
#
|
7
|
-
# mean - the mean of the dataset so far
|
8
|
-
# m2 - the running sum of the squares of the differences of the dataset
|
7
|
+
# bucket - the hash corresponding to the dataset metric
|
9
8
|
# Arguments:
|
10
9
|
# datum - the number to be added to the dataset
|
11
10
|
# Effects:
|
@@ -13,17 +12,15 @@ class RunningStat
|
|
13
12
|
# Returns:
|
14
13
|
# nothing
|
15
14
|
PUSH_DATUM = <<-EOLUA
|
16
|
-
local
|
17
|
-
local mean_key = KEYS[2]
|
18
|
-
local m2_key = KEYS[3]
|
15
|
+
local bucket_key = KEYS[1]
|
19
16
|
local datum = ARGV[1]
|
20
17
|
|
21
|
-
local mean = tonumber(redis.call("
|
18
|
+
local mean = tonumber(redis.call("HGET", bucket_key, "#{RedisBackend::MEAN_FIELD}")) or 0.0
|
22
19
|
local delta = datum - mean
|
23
20
|
|
24
|
-
local count = redis.call("
|
25
|
-
mean = redis.call("
|
26
|
-
redis.call("
|
21
|
+
local count = redis.call("HINCRBY", bucket_key, "#{RedisBackend::COUNT_FIELD}", 1)
|
22
|
+
mean = redis.call("HINCRBYFLOAT", bucket_key, "#{RedisBackend::MEAN_FIELD}", tostring(delta / count))
|
23
|
+
redis.call("HINCRBYFLOAT", bucket_key, "#{RedisBackend::M2_FIELD}", tostring(delta * (datum - mean)))
|
27
24
|
EOLUA
|
28
25
|
|
29
26
|
PUSH_DATUM_SHA1 = Digest::SHA1.hexdigest(PUSH_DATUM).freeze
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'digest/sha1'
|
2
|
+
require 'running_stat/redis_backend'
|
2
3
|
require 'running_stat/insufficient_data_error'
|
3
4
|
|
4
5
|
class RunningStat
|
5
6
|
module Lua
|
6
7
|
# Keys:
|
7
|
-
#
|
8
|
-
# m2 - the running sum of the squares of the differences of the dataset
|
8
|
+
# bucket - the hash corresponding to the dataset metric
|
9
9
|
# Arguments:
|
10
10
|
# nothing
|
11
11
|
# Effects:
|
@@ -13,14 +13,14 @@ class RunningStat
|
|
13
13
|
# Returns:
|
14
14
|
# the sample variance of the dataset, as a stringified float
|
15
15
|
VARIANCE = <<-EOLUA
|
16
|
-
local
|
17
|
-
local m2_key = KEYS[2]
|
16
|
+
local bucket_key = KEYS[1]
|
18
17
|
|
19
|
-
local
|
18
|
+
local values = redis.call("HMGET", bucket_key, "#{RedisBackend::COUNT_FIELD}", "#{RedisBackend::M2_FIELD}")
|
19
|
+
local count = tonumber(values[1]) or 0
|
20
20
|
if count < 2 then
|
21
21
|
return redis.error_reply("#{InsufficientDataError::ERROR_STRING}")
|
22
22
|
else
|
23
|
-
local m2 = tonumber(
|
23
|
+
local m2 = tonumber(values[2]) or 0.0
|
24
24
|
return tostring(m2 / (count - 1))
|
25
25
|
end
|
26
26
|
EOLUA
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class RunningStat
|
2
|
+
module RedisBackend
|
3
|
+
# fields within the metric's redis hash
|
4
|
+
COUNT_FIELD = :c # the dataset cardinality
|
5
|
+
MEAN_FIELD = :m # the arithmetic mean of the dataset
|
6
|
+
M2_FIELD = :m2 # the running sum of the squares of the differences of the dataset
|
7
|
+
|
8
|
+
# TODO: implement global redis set/get
|
9
|
+
end
|
10
|
+
end
|
data/lib/running_stat/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: running_stat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anuj Das
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/running_stat/invalid_data_error.rb
|
90
90
|
- lib/running_stat/lua/push_datum.rb
|
91
91
|
- lib/running_stat/lua/variance.rb
|
92
|
+
- lib/running_stat/redis_backend.rb
|
92
93
|
- lib/running_stat/version.rb
|
93
94
|
- running_stat.gemspec
|
94
95
|
homepage: https://www.github.com/anujdas/running_stat
|