Skip to content

Commit

Permalink
* New metric types: accumulator and delta
Browse files Browse the repository at this point in the history
* A little bit more debugging info
  • Loading branch information
divanikus committed Mar 14, 2020
1 parent 72d0293 commit 4db5327
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 4 deletions.
3 changes: 3 additions & 0 deletions lib/salus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ def save_state(&block)
end

def tick
log DEBUG, "Tick..."
lazy_eval
return if @@_groups.empty?
pause = (Salus.interval - Salus.tick_timeout - Salus.render_timeout) / 2
pause = 1 if (pause <= 0)

log DEBUG, "Starting collection. Top-level groups to spawn: #{@@_groups.count}"
latch = CountDownLatch.new(@@_groups.count)
@@_groups.each do |k, v|
pool.process do
Expand All @@ -150,6 +152,7 @@ def tick
log DEBUG, "Collection finished. Threads: #{pool.spawned} spawned, #{pool.waiting} waiting, #{Thread.list.count} total"

return if @@_renders.empty?
log DEBUG, "Starting #{@_renders.count} renderers"
latch = CountDownLatch.new(@@_renders.count)
@@_renders.each do |v|
pool.process do
Expand Down
2 changes: 2 additions & 0 deletions lib/salus/group.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "forwardable"
require "salus/metric"
require "salus/metric/absolute"
require "salus/metric/accumulator"
require "salus/metric/counter"
require "salus/metric/delta"
require "salus/metric/derive"
require "salus/metric/gauge"
require "salus/metric/text"
Expand Down
9 changes: 9 additions & 0 deletions lib/salus/metric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ def to_h
end
end

def clear
synchronize do
@last_calced_value = nil
@last_calced_ts = nil
@needs_update = true
@values.clear
end
end

protected
def option(key, *types)
@attributes[key] = types
Expand Down
34 changes: 34 additions & 0 deletions lib/salus/metric/accumulator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Salus
class Accumulator < Metric
STORAGE_DEPTH = 1

def push(opts={}, &block)
opts = {} unless opts.is_a?(Hash)

synchronize do
opts.each do |k, v|
validate(k, v)
@opts[k] = v unless [:value, :ttl, :timestamp].include?(k)
end

if block_given?
v = begin
yield
rescue Exception => e
log DEBUG, e
nil
end
validate(:value, v)
opts[:value] = v
end

prev = @values.empty? ? 0 : (@values.last.value || 0)
curr = opts[:value] || 0

@values << Value.new(prev+curr, opts[:timestamp] || Time.now.to_f, opts[:ttl] || @opts[:ttl])
@needs_update = true
end
end
end
end

36 changes: 36 additions & 0 deletions lib/salus/metric/delta.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Salus
class Delta < Metric
def initialize(defaults={})
super(defaults)
option :minimum, Numeric
validate(:minimum, @opts[:minimum]) if @opts.key?(:minimum)
end

protected
def calc
super
@last_calced_value = nil

if @values.length < STORAGE_DEPTH
return
elsif @values[0].expired?(@values[1].timestamp)
return
elsif !@values[0].value.is_a?(Numeric)
return
elsif !@values[1].value.is_a?(Numeric)
return
end

@last_calced_value = begin
dt = (@values[1].timestamp - @values[0].timestamp)
dv = (@values[1].value - @values[0].value)
r = (dt == 0) ? nil : dv
if @opts.key?(:minimum) && !r.nil? && r < @opts[:minimum]
nil
else
r
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/salus/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Salus
VERSION = "0.1.3"
VERSION = "0.2.0"
end
6 changes: 3 additions & 3 deletions salus.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_development_dependency "bundler", "~> 1.15"
spec.add_development_dependency "bundler", "~> 2.1"

spec.add_dependency "thor", "~> 0.20"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_dependency "thor", "~> 1.0"
spec.add_development_dependency "rake", ">= 12.3.3"
spec.add_development_dependency "rspec", "~> 3.0"
end
16 changes: 16 additions & 0 deletions spec/salus_accumulator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "spec_helper"

RSpec.describe Salus::Accumulator do
context "without ttl" do
let(:metric) { Salus::Accumulator.new }

it "accumulates values as pushed" do
metric.push value: 10.0
expect(metric.value).to eq(10.0)
metric.push value: 20.0
expect(metric.value).to eq(30.0)
metric.push value: 30.0
expect(metric.value).to eq(60.0)
end
end
end
52 changes: 52 additions & 0 deletions spec/salus_delta_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require "spec_helper"

RSpec.describe Salus::Delta do
context "without ttl" do
let(:metric) { Salus::Delta.new }

it "validates types" do
expect{metric.push minimum: "just a test"}.to raise_error(ArgumentError)
end

it "counts deltas" do
metric.push value: 10, timestamp: 0
expect(metric.value).to eq(nil)
metric.push value: 20, timestamp: 10
expect(metric.value).to eq(10)
metric.push value: 100, timestamp: 20
expect(metric.value).to eq(80)
end

it "returns nil rate for dt == 0" do
metric.push value: 10, timestamp: 10
metric.push value: 20, timestamp: 10
expect(metric.value).to eq(nil)
end

it "returns nil if one value is nil" do
metric.push value: 10, timestamp: 0
metric.push value: nil, timestamp: 10
expect(metric.value).to eq(nil)
end

it "returns nil if delta is less than minimum" do
metric.push value: 200, timestamp: 0, minimum: 0
metric.push value: 1000, timestamp: 10
expect(metric.value).to eq(800)
metric.push value: 1, timestamp: 20
expect(metric.value).to eq(nil)
end
end

context "with ttl" do
let(:metric) { Salus::Delta.new }

it "returns nil if previous value is expired" do
metric.push value: 0, timestamp: 0, ttl: 10
metric.push value: 5, timestamp: 5, ttl: 10
expect(metric.value).to eq(5)
metric.push value: 100, timestamp: 100, ttl: 10
expect(metric.value).to eq(nil)
end
end
end
10 changes: 10 additions & 0 deletions spec/salus_metric_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
expect(metric.value).to eq(30)
end

it "clears values" do
metric.push value: 10
expect(metric.value).to eq(10)
metric.push value: 20
expect(metric.value).to eq(20)
metric.clear
expect(metric.value).to eq(nil)
expect(metric.timestamp).to eq(nil)
end

it "takes block" do
metric.push do
100 / 10
Expand Down

0 comments on commit 4db5327

Please sign in to comment.