trifle-stats 1.3.1 → 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/local/Dockerfile +1 -0
- data/.devops/docker/local/docker-compose.yml +30 -0
- data/.github/workflows/ruby.yml +85 -6
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +8 -7
- 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 -27
- data/lib/trifle/stats/driver/postgres.rb +14 -2
- data/lib/trifle/stats/driver/process.rb +12 -0
- data/lib/trifle/stats/driver/redis.rb +19 -4
- data/lib/trifle/stats/driver/sqlite.rb +15 -2
- 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 +18 -3
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
3
4
|
require_relative '../mixins/packer'
|
4
5
|
|
5
6
|
module Trifle
|
@@ -20,6 +21,10 @@ module Trifle
|
|
20
21
|
client.execute("CREATE UNIQUE INDEX idx_#{table_name}_key ON #{table_name} (key);")
|
21
22
|
end
|
22
23
|
|
24
|
+
def description
|
25
|
+
"#{self.class.name}(J)"
|
26
|
+
end
|
27
|
+
|
23
28
|
def inc(keys:, **values)
|
24
29
|
data = self.class.pack(hash: values)
|
25
30
|
client.transaction do |c|
|
@@ -52,7 +57,7 @@ module Trifle
|
|
52
57
|
<<-SQL
|
53
58
|
INSERT INTO #{table_name} (key, data) values('#{key}', json('#{data.to_json}'))
|
54
59
|
ON CONFLICT (key) DO UPDATE SET data =
|
55
|
-
#{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})" }};
|
56
61
|
SQL
|
57
62
|
end
|
58
63
|
|
@@ -61,7 +66,7 @@ module Trifle
|
|
61
66
|
data = get_all(keys: pkeys)
|
62
67
|
map = data.inject({}) { |o, d| o.merge(d[:key] => d[:data]) }
|
63
68
|
|
64
|
-
pkeys.map { |pkey| map.fetch(pkey, {}) }
|
69
|
+
pkeys.map { |pkey| self.class.unpack(hash: map.fetch(pkey, {})) }
|
65
70
|
end
|
66
71
|
|
67
72
|
def get_all(keys:)
|
@@ -79,6 +84,14 @@ module Trifle
|
|
79
84
|
SELECT key, data FROM #{table_name} WHERE key IN ('#{keys.join("', '")}');
|
80
85
|
SQL
|
81
86
|
end
|
87
|
+
|
88
|
+
def ping(*)
|
89
|
+
[]
|
90
|
+
end
|
91
|
+
|
92
|
+
def scan(*)
|
93
|
+
[]
|
94
|
+
end
|
82
95
|
end
|
83
96
|
end
|
84
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.
|
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jozef Vaclavik
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -183,6 +183,8 @@ files:
|
|
183
183
|
- ".devops/docker/gitpod/base/.p10k.zsh"
|
184
184
|
- ".devops/docker/gitpod/base/.zshrc"
|
185
185
|
- ".devops/docker/gitpod/base/Dockerfile"
|
186
|
+
- ".devops/docker/local/Dockerfile"
|
187
|
+
- ".devops/docker/local/docker-compose.yml"
|
186
188
|
- ".github/workflows/ruby.yml"
|
187
189
|
- ".gitignore"
|
188
190
|
- ".gitpod.yml"
|
@@ -198,6 +200,10 @@ files:
|
|
198
200
|
- bin/console
|
199
201
|
- bin/setup
|
200
202
|
- lib/trifle/stats.rb
|
203
|
+
- lib/trifle/stats/aggregator/avg.rb
|
204
|
+
- lib/trifle/stats/aggregator/max.rb
|
205
|
+
- lib/trifle/stats/aggregator/min.rb
|
206
|
+
- lib/trifle/stats/aggregator/sum.rb
|
201
207
|
- lib/trifle/stats/configuration.rb
|
202
208
|
- lib/trifle/stats/designator/custom.rb
|
203
209
|
- lib/trifle/stats/designator/geometric.rb
|
@@ -208,12 +214,20 @@ files:
|
|
208
214
|
- lib/trifle/stats/driver/process.rb
|
209
215
|
- lib/trifle/stats/driver/redis.rb
|
210
216
|
- lib/trifle/stats/driver/sqlite.rb
|
217
|
+
- lib/trifle/stats/formatter/category.rb
|
218
|
+
- lib/trifle/stats/formatter/timeline.rb
|
211
219
|
- lib/trifle/stats/mixins/packer.rb
|
212
220
|
- lib/trifle/stats/nocturnal.rb
|
221
|
+
- lib/trifle/stats/operations/status/beam.rb
|
222
|
+
- lib/trifle/stats/operations/status/scan.rb
|
213
223
|
- lib/trifle/stats/operations/timeseries/classify.rb
|
214
224
|
- lib/trifle/stats/operations/timeseries/increment.rb
|
215
225
|
- lib/trifle/stats/operations/timeseries/set.rb
|
216
226
|
- lib/trifle/stats/operations/timeseries/values.rb
|
227
|
+
- lib/trifle/stats/series.rb
|
228
|
+
- lib/trifle/stats/transponder/average.rb
|
229
|
+
- lib/trifle/stats/transponder/ratio.rb
|
230
|
+
- lib/trifle/stats/transponder/standard_deviation.rb
|
217
231
|
- lib/trifle/stats/version.rb
|
218
232
|
- trifle-stats.gemspec
|
219
233
|
homepage: https://trifle.io
|
@@ -222,6 +236,7 @@ licenses:
|
|
222
236
|
metadata:
|
223
237
|
homepage_uri: https://trifle.io
|
224
238
|
source_code_uri: https://github.com/trifle-io/trifle-stats
|
239
|
+
changelog_uri: https://trifle.io/trifle-stats/changelog
|
225
240
|
post_install_message:
|
226
241
|
rdoc_options: []
|
227
242
|
require_paths:
|
@@ -237,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
252
|
- !ruby/object:Gem::Version
|
238
253
|
version: '0'
|
239
254
|
requirements: []
|
240
|
-
rubygems_version: 3.
|
255
|
+
rubygems_version: 3.3.3
|
241
256
|
signing_key:
|
242
257
|
specification_version: 4
|
243
258
|
summary: Simple analytics backed by Redis, Postgres, MongoDB, Google Analytics, Segment,
|