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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ec11d286e66a056fc873beecd760b3916008ea2
4
- data.tar.gz: 99915adeadbbe43c59c190a5392f46c85f438126
3
+ metadata.gz: 692e627aba71ce44c80b57d406c85dd69f38edfc
4
+ data.tar.gz: 0caada43394fd224b1e8932958bbe18ed1fd4815
5
5
  SHA512:
6
- metadata.gz: dc655fd6ca351e6bf5a3d9fb4331b2e704b22cd0a3551dd914ae025ad558b2a261dad16edbf7964578fc4945a7d3b54da013fc9040e83c8fb2929483f4e1e416
7
- data.tar.gz: 5ed907c0cc481824640b8df911556c509616132e991ab1a9fecf347cb54c22398132990906bff31d6a6fac7cb1d5f7848b92509486dc3b9e620043867cd6178d
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, [count_key, mean_key, sum_sq_diff_key], [Float(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.get(count_key).to_i
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.get(mean_key).to_f
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, [count_key, sum_sq_diff_key], []).to_f
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(count_key, mean_key, sum_sq_diff_key)
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 count_key
68
- "#{BASE_KEY}:#{@data_bucket}:count"
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
- # count - the dataset cardinality
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 count_key = KEYS[1]
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("GET", mean_key)) or 0.0
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("INCR", count_key)
25
- mean = redis.call("INCRBYFLOAT", mean_key, tostring(delta / count))
26
- redis.call("INCRBYFLOAT", m2_key, tostring(delta * (datum - mean)))
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
- # count - the dataset cardinality
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 count_key = KEYS[1]
17
- local m2_key = KEYS[2]
16
+ local bucket_key = KEYS[1]
18
17
 
19
- local count = tonumber(redis.call("GET", count_key)) or 0
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(redis.call("GET", m2_key)) or 0.0
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
@@ -1,3 +1,3 @@
1
1
  class RunningStat
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
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.1
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 00:00:00.000000000 Z
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