trifle-stats 1.3.0 → 1.6.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/.devcontainer.json +1 -1
- data/.devops/docker/codespaces/Dockerfile +1 -1
- data/.devops/docker/environment/Dockerfile +3 -2
- data/.devops/docker/gitpod/base/.p10k.zsh +1626 -0
- data/.devops/docker/gitpod/base/.zshrc +13 -0
- data/.devops/docker/gitpod/base/Dockerfile +9 -32
- data/.devops/docker/local/Dockerfile +1 -0
- data/.devops/docker/local/docker-compose.yml +30 -0
- data/.github/workflows/ruby.yml +85 -6
- data/.gitignore +3 -1
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +11 -8
- data/README.md +31 -0
- data/lib/trifle/stats/aggregator/avg.rb +32 -0
- data/lib/trifle/stats/aggregator/max.rb +29 -0
- data/lib/trifle/stats/aggregator/min.rb +29 -0
- data/lib/trifle/stats/aggregator/sum.rb +29 -0
- data/lib/trifle/stats/driver/mongo.rb +81 -28
- data/lib/trifle/stats/driver/postgres.rb +14 -3
- data/lib/trifle/stats/driver/process.rb +12 -0
- data/lib/trifle/stats/driver/redis.rb +19 -5
- data/lib/trifle/stats/driver/sqlite.rb +15 -3
- data/lib/trifle/stats/formatter/category.rb +32 -0
- data/lib/trifle/stats/formatter/timeline.rb +29 -0
- data/lib/trifle/stats/mixins/packer.rb +16 -1
- data/lib/trifle/stats/nocturnal.rb +24 -0
- data/lib/trifle/stats/operations/status/beam.rb +31 -0
- data/lib/trifle/stats/operations/status/scan.rb +35 -0
- data/lib/trifle/stats/operations/timeseries/classify.rb +1 -1
- data/lib/trifle/stats/operations/timeseries/increment.rb +1 -1
- data/lib/trifle/stats/operations/timeseries/set.rb +1 -1
- data/lib/trifle/stats/operations/timeseries/values.rb +25 -7
- data/lib/trifle/stats/series.rb +64 -0
- data/lib/trifle/stats/transponder/average.rb +31 -0
- data/lib/trifle/stats/transponder/ratio.rb +31 -0
- data/lib/trifle/stats/transponder/standard_deviation.rb +35 -0
- data/lib/trifle/stats/version.rb +1 -1
- data/lib/trifle/stats.rb +36 -3
- data/trifle-stats.gemspec +1 -0
- metadata +20 -3
@@ -12,6 +12,10 @@ module Trifle
|
|
12
12
|
@separator = '::'
|
13
13
|
end
|
14
14
|
|
15
|
+
def description
|
16
|
+
"#{self.class.name}(J)"
|
17
|
+
end
|
18
|
+
|
15
19
|
def inc(keys:, **values)
|
16
20
|
keys.map do |key|
|
17
21
|
self.class.pack(hash: values).each do |k, c|
|
@@ -39,6 +43,14 @@ module Trifle
|
|
39
43
|
)
|
40
44
|
end
|
41
45
|
end
|
46
|
+
|
47
|
+
def ping(*)
|
48
|
+
[]
|
49
|
+
end
|
50
|
+
|
51
|
+
def scan(*)
|
52
|
+
[]
|
53
|
+
end
|
42
54
|
end
|
43
55
|
end
|
44
56
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'redis'
|
4
3
|
require_relative '../mixins/packer'
|
5
4
|
|
6
5
|
module Trifle
|
@@ -10,15 +9,20 @@ module Trifle
|
|
10
9
|
include Mixins::Packer
|
11
10
|
attr_accessor :client, :prefix, :separator
|
12
11
|
|
13
|
-
def initialize(client
|
12
|
+
def initialize(client, prefix: 'trfl')
|
14
13
|
@client = client
|
15
14
|
@prefix = prefix
|
16
15
|
@separator = '::'
|
17
16
|
end
|
18
17
|
|
18
|
+
def description
|
19
|
+
"#{self.class.name}(J)"
|
20
|
+
end
|
21
|
+
|
19
22
|
def inc(keys:, **values)
|
20
23
|
keys.map do |key|
|
21
|
-
|
24
|
+
key.prefix = prefix
|
25
|
+
pkey = key.join(separator)
|
22
26
|
|
23
27
|
self.class.pack(hash: values).each do |k, c|
|
24
28
|
client.hincrby(pkey, k, c)
|
@@ -28,7 +32,8 @@ module Trifle
|
|
28
32
|
|
29
33
|
def set(keys:, **values)
|
30
34
|
keys.map do |key|
|
31
|
-
|
35
|
+
key.prefix = prefix
|
36
|
+
pkey = key.join(separator)
|
32
37
|
|
33
38
|
client.hmset(pkey, *self.class.pack(hash: values))
|
34
39
|
end
|
@@ -36,13 +41,22 @@ module Trifle
|
|
36
41
|
|
37
42
|
def get(keys:)
|
38
43
|
keys.map do |key|
|
39
|
-
|
44
|
+
key.prefix = prefix
|
45
|
+
pkey = key.join(separator)
|
40
46
|
|
41
47
|
self.class.unpack(
|
42
48
|
hash: client.hgetall(pkey)
|
43
49
|
)
|
44
50
|
end
|
45
51
|
end
|
52
|
+
|
53
|
+
def ping(*)
|
54
|
+
[]
|
55
|
+
end
|
56
|
+
|
57
|
+
def scan(*)
|
58
|
+
[]
|
59
|
+
end
|
46
60
|
end
|
47
61
|
end
|
48
62
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'json'
|
4
4
|
require_relative '../mixins/packer'
|
5
5
|
|
6
6
|
module Trifle
|
@@ -21,6 +21,10 @@ module Trifle
|
|
21
21
|
client.execute("CREATE UNIQUE INDEX idx_#{table_name}_key ON #{table_name} (key);")
|
22
22
|
end
|
23
23
|
|
24
|
+
def description
|
25
|
+
"#{self.class.name}(J)"
|
26
|
+
end
|
27
|
+
|
24
28
|
def inc(keys:, **values)
|
25
29
|
data = self.class.pack(hash: values)
|
26
30
|
client.transaction do |c|
|
@@ -53,7 +57,7 @@ module Trifle
|
|
53
57
|
<<-SQL
|
54
58
|
INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
|
55
59
|
ON CONFLICT (key) DO UPDATE SET data =
|
56
|
-
#{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', #{v})" }};
|
60
|
+
#{data.inject('data') { |o, (k, v)| "json_set(#{o}, '$.#{k}', #{v.to_json})" }};
|
57
61
|
SQL
|
58
62
|
end
|
59
63
|
|
@@ -62,7 +66,7 @@ module Trifle
|
|
62
66
|
data = get_all(keys: pkeys)
|
63
67
|
map = data.inject({}) { |o, d| o.merge(d[:key] => d[:data]) }
|
64
68
|
|
65
|
-
pkeys.map { |pkey| map.fetch(pkey, {}) }
|
69
|
+
pkeys.map { |pkey| self.class.unpack(hash: map.fetch(pkey, {})) }
|
66
70
|
end
|
67
71
|
|
68
72
|
def get_all(keys:)
|
@@ -80,6 +84,14 @@ module Trifle
|
|
80
84
|
SELECT key, data FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');
|
81
85
|
SQL
|
82
86
|
end
|
87
|
+
|
88
|
+
def ping(*)
|
89
|
+
[]
|
90
|
+
end
|
91
|
+
|
92
|
+
def scan(*)
|
93
|
+
[]
|
94
|
+
end
|
83
95
|
end
|
84
96
|
end
|
85
97
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Formatter
|
6
|
+
class Category
|
7
|
+
Trifle::Stats::Series.register_formatter(:category, self)
|
8
|
+
|
9
|
+
def format(series:, path:, slices: 1, &block)
|
10
|
+
return [] if series[:at].empty?
|
11
|
+
|
12
|
+
keys = path.split('.')
|
13
|
+
result = series[:at].zip(series[:values].map { |v| v.dig(*keys) || {} })
|
14
|
+
sliced(result: result, slices: slices, block: block)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def sliced(result:, slices:, block: nil) # rubocop:disable Metrics/AbcSize
|
20
|
+
result[(result.count - (result.count / slices * slices))..].each_slice(result.count / slices).map do |slice|
|
21
|
+
slice.each_with_object(Hash.new(0)) do |(_at, data), map|
|
22
|
+
data.each do |key, value|
|
23
|
+
k, v = block ? block.call(key, value) : [key.to_s, value.to_f]
|
24
|
+
map[k] += v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Formatter
|
6
|
+
class Timeline
|
7
|
+
Trifle::Stats::Series.register_formatter(:timeline, self)
|
8
|
+
|
9
|
+
def format(series:, path:, slices: 1, &block)
|
10
|
+
return [] if series[:at].empty?
|
11
|
+
|
12
|
+
keys = path.split('.')
|
13
|
+
result = series[:at].zip(series[:values].map { |v| v.dig(*keys) })
|
14
|
+
sliced(result: result, slices: slices, block: block)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def sliced(result:, slices:, block: nil)
|
20
|
+
result[(result.count - (result.count / slices * slices))..].each_slice(result.count / slices).map do |slice|
|
21
|
+
slice.map do |at, value|
|
22
|
+
block ? block.call(at, value) : [at, value.to_f]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'bigdecimal'
|
4
|
+
|
3
5
|
module Trifle
|
4
6
|
module Stats
|
5
7
|
module Mixins
|
@@ -26,7 +28,7 @@ module Trifle
|
|
26
28
|
hash.inject({}) do |out, (key, v)|
|
27
29
|
deep_merge(
|
28
30
|
out,
|
29
|
-
key.split('.').reverse.inject(v
|
31
|
+
key.split('.').reverse.inject(v) { |o, k| { k => o } }
|
30
32
|
)
|
31
33
|
end
|
32
34
|
end
|
@@ -46,6 +48,19 @@ module Trifle
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
51
|
+
|
52
|
+
def normalize(object)
|
53
|
+
case object
|
54
|
+
when Hash
|
55
|
+
object.each_with_object({}) do |(key, value), result|
|
56
|
+
result[key.to_s] = normalize(value)
|
57
|
+
end
|
58
|
+
when Array
|
59
|
+
object.map { |v| normalize(v) }
|
60
|
+
else
|
61
|
+
BigDecimal(object)
|
62
|
+
end
|
63
|
+
end
|
49
64
|
end
|
50
65
|
end
|
51
66
|
end
|
@@ -3,6 +3,30 @@
|
|
3
3
|
module Trifle
|
4
4
|
module Stats
|
5
5
|
class Nocturnal # rubocop:disable Metrics/ClassLength
|
6
|
+
class Key
|
7
|
+
attr_reader :key, :range, :at
|
8
|
+
attr_accessor :prefix
|
9
|
+
|
10
|
+
def initialize(key:, range: nil, at: nil)
|
11
|
+
@prefix = nil
|
12
|
+
@key = key
|
13
|
+
@range = range
|
14
|
+
@at = at
|
15
|
+
end
|
16
|
+
|
17
|
+
def join(separator)
|
18
|
+
[prefix, key, range, at&.to_i].compact.join(separator)
|
19
|
+
end
|
20
|
+
|
21
|
+
def identifier(separator)
|
22
|
+
if separator
|
23
|
+
{ key: join(separator) }
|
24
|
+
else
|
25
|
+
{ key: key, range: range, at: at }.compact
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
6
30
|
DAYS_INTO_WEEK = {
|
7
31
|
sunday: 0, monday: 1, tuesday: 2, wednesday: 3,
|
8
32
|
thursday: 4, friday: 5, saturday: 6
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
module Operations
|
6
|
+
module Status
|
7
|
+
class Beam
|
8
|
+
attr_reader :key, :at, :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 perform
|
22
|
+
config.driver.ping(
|
23
|
+
key: Nocturnal::Key.new(key: key, at: at),
|
24
|
+
**values
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
module Operations
|
6
|
+
module Status
|
7
|
+
class Scan
|
8
|
+
attr_reader :key
|
9
|
+
|
10
|
+
def initialize(**keywords)
|
11
|
+
@key = keywords.fetch(:key)
|
12
|
+
@config = keywords[:config]
|
13
|
+
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
@config || Trifle::Stats.default
|
17
|
+
end
|
18
|
+
|
19
|
+
def data
|
20
|
+
@data ||= config.driver.scan(
|
21
|
+
key: Nocturnal::Key.new(key: key)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def perform
|
26
|
+
{
|
27
|
+
at: data.first,
|
28
|
+
values: data.last
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -13,6 +13,7 @@ module Trifle
|
|
13
13
|
@to = keywords.fetch(:to)
|
14
14
|
@range = keywords.fetch(:range)
|
15
15
|
@config = keywords[:config]
|
16
|
+
@skip_blanks = keywords[:skip_blanks]
|
16
17
|
end
|
17
18
|
|
18
19
|
def config
|
@@ -20,19 +21,36 @@ module Trifle
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def timeline
|
23
|
-
Nocturnal.timeline(from: @from, to: @to, range: range)
|
24
|
+
@timeline ||= Nocturnal.timeline(from: @from, to: @to, range: range)
|
24
25
|
end
|
25
26
|
|
26
|
-
def
|
27
|
+
def data
|
28
|
+
@data ||= config.driver.get(
|
29
|
+
keys: timeline.map do |at|
|
30
|
+
Nocturnal::Key.new(key: key, range: range, at: at)
|
31
|
+
end
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def clean_values
|
36
|
+
timeline.each_with_object({ at: [], values: [] }).with_index do |(_at, res), idx|
|
37
|
+
next if data[idx].empty?
|
38
|
+
|
39
|
+
res[:at] << timeline[idx]
|
40
|
+
res[:values] << data[idx]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def values
|
27
45
|
{
|
28
46
|
at: timeline,
|
29
|
-
values:
|
30
|
-
keys: timeline.map do |at|
|
31
|
-
[key, range, at.to_i]
|
32
|
-
end
|
33
|
-
)
|
47
|
+
values: data
|
34
48
|
}
|
35
49
|
end
|
50
|
+
|
51
|
+
def perform
|
52
|
+
@skip_blanks ? clean_values : values
|
53
|
+
end
|
36
54
|
end
|
37
55
|
end
|
38
56
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Series
|
6
|
+
include Trifle::Stats::Mixins::Packer
|
7
|
+
|
8
|
+
attr_accessor :series
|
9
|
+
|
10
|
+
def initialize(series)
|
11
|
+
@series = series
|
12
|
+
@series[:values] = self.class.normalize(@series[:values])
|
13
|
+
end
|
14
|
+
|
15
|
+
class Aggregator
|
16
|
+
def initialize(series)
|
17
|
+
@series = series
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def aggregate
|
22
|
+
@aggregate ||= Aggregator.new(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.register_aggregator(name, klass)
|
26
|
+
Aggregator.define_method(name) do |params|
|
27
|
+
klass.new.aggregate(series: @series.series, **params)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Formatter
|
32
|
+
def initialize(series)
|
33
|
+
@series = series
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def format
|
38
|
+
@format ||= Formatter.new(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.register_formatter(name, klass)
|
42
|
+
Formatter.define_method(name) do |params, &block|
|
43
|
+
klass.new.format(series: @series.series, **params, &block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Transponder
|
48
|
+
def initialize(series)
|
49
|
+
@series = series
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def transpond
|
54
|
+
@transpond ||= Transponder.new(self)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.register_transponder(name, klass)
|
58
|
+
Transponder.define_method(name) do |params|
|
59
|
+
@series.series = klass.new.transpond(series: @series.series, **params)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Transponder
|
6
|
+
class Average
|
7
|
+
include Trifle::Stats::Mixins::Packer
|
8
|
+
Trifle::Stats::Series.register_transponder(:average, self)
|
9
|
+
|
10
|
+
def transpond(series:, path:, key: 'average', sum: 'sum', count: 'count') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
11
|
+
keys = path.to_s.split('.')
|
12
|
+
sum = sum.to_s.split('.')
|
13
|
+
count = count.to_s.split('.')
|
14
|
+
key = path.to_s.empty? ? key : [path, key].join('.')
|
15
|
+
series[:values] = series[:values].map do |data|
|
16
|
+
dsum = data.dig(*keys, *sum)
|
17
|
+
dcount = data.dig(*keys, *count)
|
18
|
+
next data unless dsum && dcount
|
19
|
+
|
20
|
+
dres = (dsum / dcount)
|
21
|
+
signal = {
|
22
|
+
key => dres.nan? ? BigDecimal(0) : dres
|
23
|
+
}
|
24
|
+
self.class.deep_merge(data, self.class.unpack(hash: signal))
|
25
|
+
end
|
26
|
+
series
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Transponder
|
6
|
+
class Ratio
|
7
|
+
include Trifle::Stats::Mixins::Packer
|
8
|
+
Trifle::Stats::Series.register_transponder(:ratio, self)
|
9
|
+
|
10
|
+
def transpond(series:, path:, key: 'ratio', sample: 'sample', total: 'total') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
11
|
+
keys = path.to_s.split('.')
|
12
|
+
sample = sample.to_s.split('.')
|
13
|
+
total = total.to_s.split('.')
|
14
|
+
key = path.to_s.empty? ? key : [path, key].join('.')
|
15
|
+
series[:values] = series[:values].map do |data|
|
16
|
+
dsample = data.dig(*keys, *sample)
|
17
|
+
dtotal = data.dig(*keys, *total)
|
18
|
+
next data unless dsample && dtotal
|
19
|
+
|
20
|
+
dres = (dsample / dtotal) * 100
|
21
|
+
signal = {
|
22
|
+
key => dres.nan? ? BigDecimal(0) : dres
|
23
|
+
}
|
24
|
+
self.class.deep_merge(data, self.class.unpack(hash: signal))
|
25
|
+
end
|
26
|
+
series
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Trifle
|
4
|
+
module Stats
|
5
|
+
class Transponder
|
6
|
+
class StandardDeviation
|
7
|
+
include Trifle::Stats::Mixins::Packer
|
8
|
+
Trifle::Stats::Series.register_transponder(:standard_deviation, self)
|
9
|
+
|
10
|
+
def transpond(series:, path:, key: 'sd', sum: 'sum', count: 'count', square: 'square') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists
|
11
|
+
keys = path.to_s.split('.')
|
12
|
+
sum = sum.to_s.split('.')
|
13
|
+
count = count.to_s.split('.')
|
14
|
+
square = square.to_s.split('.')
|
15
|
+
key = path.to_s.empty? ? key : [path, key].join('.')
|
16
|
+
series[:values] = series[:values].map do |data|
|
17
|
+
dcount = data.dig(*keys, *count)
|
18
|
+
dsquare = data.dig(*keys, *square)
|
19
|
+
dsum = data.dig(*keys, *sum)
|
20
|
+
next data unless dcount && dsquare && dsum
|
21
|
+
|
22
|
+
dres = Math.sqrt(
|
23
|
+
(dcount * dsquare - dsum * dsum) / (dcount * (dcount - 1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
|
24
|
+
)
|
25
|
+
signal = {
|
26
|
+
key => dres.nan? ? BigDecimal(0) : dres
|
27
|
+
}
|
28
|
+
self.class.deep_merge(data, self.class.unpack(hash: signal))
|
29
|
+
end
|
30
|
+
series
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/trifle/stats/version.rb
CHANGED
data/lib/trifle/stats.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'trifle/stats/mixins/packer'
|
4
|
+
require 'trifle/stats/nocturnal'
|
5
|
+
require 'trifle/stats/series'
|
6
|
+
require 'trifle/stats/aggregator/avg'
|
7
|
+
require 'trifle/stats/aggregator/max'
|
8
|
+
require 'trifle/stats/aggregator/min'
|
9
|
+
require 'trifle/stats/aggregator/sum'
|
3
10
|
require 'trifle/stats/designator/custom'
|
4
11
|
require 'trifle/stats/designator/geometric'
|
5
12
|
require 'trifle/stats/designator/linear'
|
@@ -8,13 +15,18 @@ require 'trifle/stats/driver/postgres'
|
|
8
15
|
require 'trifle/stats/driver/process'
|
9
16
|
require 'trifle/stats/driver/redis'
|
10
17
|
require 'trifle/stats/driver/sqlite'
|
11
|
-
require 'trifle/stats/
|
12
|
-
require 'trifle/stats/
|
18
|
+
require 'trifle/stats/formatter/category'
|
19
|
+
require 'trifle/stats/formatter/timeline'
|
13
20
|
require 'trifle/stats/configuration'
|
14
21
|
require 'trifle/stats/operations/timeseries/classify'
|
15
22
|
require 'trifle/stats/operations/timeseries/increment'
|
16
23
|
require 'trifle/stats/operations/timeseries/set'
|
17
24
|
require 'trifle/stats/operations/timeseries/values'
|
25
|
+
require 'trifle/stats/operations/status/beam'
|
26
|
+
require 'trifle/stats/operations/status/scan'
|
27
|
+
require 'trifle/stats/transponder/average'
|
28
|
+
require 'trifle/stats/transponder/ratio'
|
29
|
+
require 'trifle/stats/transponder/standard_deviation'
|
18
30
|
require 'trifle/stats/version'
|
19
31
|
|
20
32
|
module Trifle
|
@@ -59,12 +71,33 @@ module Trifle
|
|
59
71
|
).perform
|
60
72
|
end
|
61
73
|
|
62
|
-
def self.values(key:, from:, to:, range:, config: nil)
|
74
|
+
def self.values(key:, from:, to:, range:, skip_blanks: false, config: nil) # rubocop:disable Metrics/ParameterLists
|
63
75
|
Trifle::Stats::Operations::Timeseries::Values.new(
|
64
76
|
key: key,
|
65
77
|
from: from,
|
66
78
|
to: to,
|
67
79
|
range: range,
|
80
|
+
skip_blanks: skip_blanks,
|
81
|
+
config: config
|
82
|
+
).perform
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.series(**params)
|
86
|
+
Trifle::Stats::Series.new(values(**params))
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.beam(key:, at:, values:, config: nil)
|
90
|
+
Trifle::Stats::Operations::Status::Beam.new(
|
91
|
+
key: key,
|
92
|
+
at: at,
|
93
|
+
values: values,
|
94
|
+
config: config
|
95
|
+
).perform
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.scan(key:, config: nil)
|
99
|
+
Trifle::Stats::Operations::Status::Scan.new(
|
100
|
+
key: key,
|
68
101
|
config: config
|
69
102
|
).perform
|
70
103
|
end
|
data/trifle-stats.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.metadata['homepage_uri'] = spec.homepage
|
20
20
|
spec.metadata['source_code_uri'] = 'https://github.com/trifle-io/trifle-stats'
|
21
|
+
spec.metadata['changelog_uri'] = 'https://trifle.io/trifle-stats/changelog'
|
21
22
|
|
22
23
|
# Specify which files should be added to the gem when it is released.
|
23
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|