trifle-stats 1.0.0 → 1.1.1
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/Gemfile.lock +1 -1
- data/lib/trifle/stats/configuration.rb +2 -1
- data/lib/trifle/stats/designator/custom.rb +22 -0
- data/lib/trifle/stats/designator/geometric.rb +25 -0
- data/lib/trifle/stats/designator/linear.rb +24 -0
- data/lib/trifle/stats/driver/README.md +2 -2
- data/lib/trifle/stats/driver/mongo.rb +11 -8
- data/lib/trifle/stats/driver/postgres.rb +11 -7
- data/lib/trifle/stats/driver/process.rb +14 -10
- data/lib/trifle/stats/driver/redis.rb +11 -7
- data/lib/trifle/stats/operations/timeseries/classify.rb +48 -0
- data/lib/trifle/stats/operations/timeseries/increment.rb +9 -7
- data/lib/trifle/stats/operations/timeseries/set.rb +9 -7
- data/lib/trifle/stats/version.rb +1 -1
- data/lib/trifle/stats.rb +13 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2ab7e87008ccd472bcbb2f821db69a304c0d2be078827150d828459c62b9ffa
|
4
|
+
data.tar.gz: 7e6b5b77c70845d2c2d7b5b29f7a9811bba32f166f3a6204fb13e931c29ab90e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49870c3899c775ce1a91a857cc39f9cc92c05b6bb7ffe211ecf52adf033436942f5db44942cd4e2f84143b8111e586b25254f88f4d9c4cf8c9123adac20503e8
|
7
|
+
data.tar.gz: 3dee093eed89e39a2dbc0c867dba0529359a9cba84f11c021fad8a78246e2e0d1115119ee896658e8ed917546757423432078faece8c582f559923b973170938
|
data/Gemfile.lock
CHANGED
@@ -6,12 +6,13 @@ module Trifle
|
|
6
6
|
module Stats
|
7
7
|
class Configuration
|
8
8
|
attr_writer :driver
|
9
|
-
attr_accessor :track_ranges, :time_zone, :beginning_of_week
|
9
|
+
attr_accessor :track_ranges, :time_zone, :beginning_of_week, :designator
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@ranges = %i[minute hour day week month quarter year]
|
13
13
|
@beginning_of_week = :monday
|
14
14
|
@time_zone = 'GMT'
|
15
|
+
@designator = nil
|
15
16
|
end
|
16
17
|
|
17
18
|
def tz
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Designator
|
6
|
+
class Custom
|
7
|
+
attr_reader :buckets
|
8
|
+
|
9
|
+
def initialize(buckets:)
|
10
|
+
@buckets = buckets.sort
|
11
|
+
end
|
12
|
+
|
13
|
+
def designate(value:)
|
14
|
+
return buckets.first.to_s if value <= buckets.first
|
15
|
+
return "#{buckets.last}+" if value > buckets.last
|
16
|
+
|
17
|
+
(buckets.find { |b| value.ceil < b }).to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Designator
|
6
|
+
class Geometric
|
7
|
+
attr_reader :min, :max
|
8
|
+
|
9
|
+
def initialize(min:, max:)
|
10
|
+
@min = min.negative? ? 0 : min
|
11
|
+
@max = max
|
12
|
+
end
|
13
|
+
|
14
|
+
def designate(value:) # rubocop:disable Metrics/AbcSize
|
15
|
+
return min.to_f.to_s if value <= min
|
16
|
+
return "#{max.to_f}+" if value > max
|
17
|
+
return (10**value.floor.to_s.length).to_f.to_s if value > 1
|
18
|
+
return 1.0.to_s if value > 0.1 # ugh?
|
19
|
+
|
20
|
+
(1.0 / 10**value.to_s.gsub('0.', '').split(/[1-9]/).first.length).to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Designator
|
6
|
+
class Linear
|
7
|
+
attr_reader :min, :max, :step
|
8
|
+
|
9
|
+
def initialize(min:, max:, step:)
|
10
|
+
@min = min
|
11
|
+
@max = max
|
12
|
+
@step = step.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
def designate(value:) # rubocop:disable Metrics/AbcSize
|
16
|
+
return min.to_s if value <= min
|
17
|
+
return "#{max}+" if value > max
|
18
|
+
|
19
|
+
(value.ceil / step * step + ((value.ceil % step).zero? ? 0 : step)).to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
Driver is a wrapper class that persists and retrieves values from backend. It needs to implement:
|
4
4
|
|
5
|
-
- `inc(
|
6
|
-
- `set(
|
5
|
+
- `inc(keys:, **values)` method increment values
|
6
|
+
- `set(keys:, **values)` method set values
|
7
7
|
- `get(keys:)` method to retrieve values
|
8
8
|
|
9
9
|
## Documentation
|
@@ -16,24 +16,27 @@ module Trifle
|
|
16
16
|
@separator = '::'
|
17
17
|
end
|
18
18
|
|
19
|
-
def inc(
|
20
|
-
|
19
|
+
def inc(keys:, **values)
|
20
|
+
data = self.class.pack(hash: { data: values })
|
21
21
|
|
22
22
|
collection.bulk_write(
|
23
|
-
|
23
|
+
keys.map do |key|
|
24
|
+
upsert_operation('$inc', pkey: key.join(separator), data: data)
|
25
|
+
end
|
24
26
|
)
|
25
27
|
end
|
26
28
|
|
27
|
-
def set(
|
28
|
-
|
29
|
+
def set(keys:, **values)
|
30
|
+
data = self.class.pack(hash: { data: values })
|
29
31
|
|
30
32
|
collection.bulk_write(
|
31
|
-
|
33
|
+
keys.map do |key|
|
34
|
+
upsert_operation('$set', pkey: key.join(separator), data: data)
|
35
|
+
end
|
32
36
|
)
|
33
37
|
end
|
34
38
|
|
35
|
-
def upsert_operation(operation, pkey:,
|
36
|
-
data = self.class.pack(hash: { data: values })
|
39
|
+
def upsert_operation(operation, pkey:, data:)
|
37
40
|
{
|
38
41
|
update_many: {
|
39
42
|
filter: { key: pkey },
|
@@ -16,11 +16,13 @@ module Trifle
|
|
16
16
|
@separator = '::'
|
17
17
|
end
|
18
18
|
|
19
|
-
def inc(
|
20
|
-
|
19
|
+
def inc(keys:, **values)
|
20
|
+
keys.map do |key|
|
21
|
+
pkey = key.join(separator)
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
self.class.pack(hash: values).each do |k, c|
|
24
|
+
_inc_one(key: pkey, name: k, value: c)
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -31,10 +33,12 @@ module Trifle
|
|
31
33
|
client.exec(query)
|
32
34
|
end
|
33
35
|
|
34
|
-
def set(
|
35
|
-
|
36
|
+
def set(keys:, **values)
|
37
|
+
keys.map do |key|
|
38
|
+
pkey = key.join(separator)
|
36
39
|
|
37
|
-
|
40
|
+
_set_all(key: pkey, **values)
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
def _set_all(key:, **values)
|
@@ -12,19 +12,23 @@ module Trifle
|
|
12
12
|
@separator = '::'
|
13
13
|
end
|
14
14
|
|
15
|
-
def inc(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def inc(keys:, **values)
|
16
|
+
keys.map do |key|
|
17
|
+
self.class.pack(hash: values).each do |k, c|
|
18
|
+
d = @data.fetch(key.join(@separator), {})
|
19
|
+
d[k] = d[k].to_i + c
|
20
|
+
@data[key.join(@separator)] = d
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
def set(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def set(keys:, **values)
|
26
|
+
keys.map do |key|
|
27
|
+
self.class.pack(hash: values).each do |k, c|
|
28
|
+
d = @data.fetch(key.join(@separator), {})
|
29
|
+
d[k] = c
|
30
|
+
@data[key.join(@separator)] = d
|
31
|
+
end
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -16,18 +16,22 @@ module Trifle
|
|
16
16
|
@separator = '::'
|
17
17
|
end
|
18
18
|
|
19
|
-
def inc(
|
20
|
-
|
19
|
+
def inc(keys:, **values)
|
20
|
+
keys.map do |key|
|
21
|
+
pkey = ([prefix] + key).join(separator)
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
self.class.pack(hash: values).each do |k, c|
|
24
|
+
client.hincrby(pkey, k, c)
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
def set(
|
28
|
-
|
29
|
+
def set(keys:, **values)
|
30
|
+
keys.map do |key|
|
31
|
+
pkey = ([prefix] + key).join(separator)
|
29
32
|
|
30
|
-
|
33
|
+
client.hmset(pkey, *self.class.pack(hash: values))
|
34
|
+
end
|
31
35
|
end
|
32
36
|
|
33
37
|
def get(keys:)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
module Operations
|
6
|
+
module Timeseries
|
7
|
+
class Classify
|
8
|
+
attr_reader :key, :values
|
9
|
+
|
10
|
+
def initialize(**keywords)
|
11
|
+
@key = keywords.fetch(:key)
|
12
|
+
@at = keywords.fetch(:at)
|
13
|
+
@values = keywords.fetch(:values)
|
14
|
+
@config = keywords[:config]
|
15
|
+
end
|
16
|
+
|
17
|
+
def config
|
18
|
+
@config || Trifle::Stats.default
|
19
|
+
end
|
20
|
+
|
21
|
+
def deep_classify(hash)
|
22
|
+
hash.transform_values do |value|
|
23
|
+
next deep_classify(value) if value.is_a?(Hash)
|
24
|
+
|
25
|
+
{ classify(value) => 1 }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def classify(value)
|
30
|
+
config.designator.designate(value: value).to_s.gsub('.', '_')
|
31
|
+
end
|
32
|
+
|
33
|
+
def key_for(range:)
|
34
|
+
at = Nocturnal.new(@at, config: config).send(range)
|
35
|
+
[key, range, at.to_i]
|
36
|
+
end
|
37
|
+
|
38
|
+
def perform
|
39
|
+
config.driver.inc(
|
40
|
+
keys: config.ranges.map { |range| key_for(range: range) },
|
41
|
+
**deep_classify(values)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -18,14 +18,16 @@ module Trifle
|
|
18
18
|
@config || Trifle::Stats.default
|
19
19
|
end
|
20
20
|
|
21
|
+
def key_for(range:)
|
22
|
+
at = Nocturnal.new(@at, config: config).send(range)
|
23
|
+
[key, range, at.to_i]
|
24
|
+
end
|
25
|
+
|
21
26
|
def perform
|
22
|
-
config.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
**values
|
27
|
-
)
|
28
|
-
end
|
27
|
+
config.driver.inc(
|
28
|
+
keys: config.ranges.map { |range| key_for(range: range) },
|
29
|
+
**values
|
30
|
+
)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -18,14 +18,16 @@ module Trifle
|
|
18
18
|
@config || Trifle::Stats.default
|
19
19
|
end
|
20
20
|
|
21
|
+
def key_for(range:)
|
22
|
+
at = Nocturnal.new(@at, config: config).send(range)
|
23
|
+
[key, range, at.to_i]
|
24
|
+
end
|
25
|
+
|
21
26
|
def perform
|
22
|
-
config.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
**values
|
27
|
-
)
|
28
|
-
end
|
27
|
+
config.driver.set(
|
28
|
+
keys: config.ranges.map { |range| key_for(range: range) },
|
29
|
+
**values
|
30
|
+
)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/trifle/stats/version.rb
CHANGED
data/lib/trifle/stats.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'trifle/stats/designator/custom'
|
4
|
+
require 'trifle/stats/designator/geometric'
|
5
|
+
require 'trifle/stats/designator/linear'
|
3
6
|
require 'trifle/stats/driver/mongo'
|
4
7
|
require 'trifle/stats/driver/postgres'
|
5
8
|
require 'trifle/stats/driver/process'
|
@@ -7,6 +10,7 @@ require 'trifle/stats/driver/redis'
|
|
7
10
|
require 'trifle/stats/mixins/packer'
|
8
11
|
require 'trifle/stats/nocturnal'
|
9
12
|
require 'trifle/stats/configuration'
|
13
|
+
require 'trifle/stats/operations/timeseries/classify'
|
10
14
|
require 'trifle/stats/operations/timeseries/increment'
|
11
15
|
require 'trifle/stats/operations/timeseries/set'
|
12
16
|
require 'trifle/stats/operations/timeseries/values'
|
@@ -45,6 +49,15 @@ module Trifle
|
|
45
49
|
).perform
|
46
50
|
end
|
47
51
|
|
52
|
+
def self.assort(key:, at:, values:, config: nil)
|
53
|
+
Trifle::Stats::Operations::Timeseries::Classify.new(
|
54
|
+
key: key,
|
55
|
+
at: at,
|
56
|
+
values: values,
|
57
|
+
config: config
|
58
|
+
).perform
|
59
|
+
end
|
60
|
+
|
48
61
|
def self.values(key:, from:, to:, range:, config: nil)
|
49
62
|
Trifle::Stats::Operations::Timeseries::Values.new(
|
50
63
|
key: key,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trifle-stats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jozef Vaclavik
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -183,6 +183,9 @@ files:
|
|
183
183
|
- bin/setup
|
184
184
|
- lib/trifle/stats.rb
|
185
185
|
- lib/trifle/stats/configuration.rb
|
186
|
+
- lib/trifle/stats/designator/custom.rb
|
187
|
+
- lib/trifle/stats/designator/geometric.rb
|
188
|
+
- lib/trifle/stats/designator/linear.rb
|
186
189
|
- lib/trifle/stats/driver/README.md
|
187
190
|
- lib/trifle/stats/driver/mongo.rb
|
188
191
|
- lib/trifle/stats/driver/postgres.rb
|
@@ -190,6 +193,7 @@ files:
|
|
190
193
|
- lib/trifle/stats/driver/redis.rb
|
191
194
|
- lib/trifle/stats/mixins/packer.rb
|
192
195
|
- lib/trifle/stats/nocturnal.rb
|
196
|
+
- lib/trifle/stats/operations/timeseries/classify.rb
|
193
197
|
- lib/trifle/stats/operations/timeseries/increment.rb
|
194
198
|
- lib/trifle/stats/operations/timeseries/set.rb
|
195
199
|
- lib/trifle/stats/operations/timeseries/values.rb
|