Class: Amigo::Autoscaler::Checkers::WebLatency

Inherits:
Amigo::Autoscaler::Checker show all
Defined in:
lib/amigo/autoscaler/checkers/web_latency.rb

Defined Under Namespace

Classes: Middleware

Constant Summary collapse

NAMESPACE =
"amigo/autoscaler/web_latency"
WINDOW =

The number of seconds requests are we averaging across.

60
MINIMUM_CONFIDENCE_WINDOW =

The number of seconds above which we have confidence in latency measurements. Without this window, a single request (without any other requests) could create a latency event. We need to see requests from this many seconds before feeling confident.

30

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(redis:, namespace: NAMESPACE) ⇒ WebLatency

Returns a new instance of WebLatency.



31
32
33
34
35
# File 'lib/amigo/autoscaler/checkers/web_latency.rb', line 31

def initialize(redis:, namespace: NAMESPACE)
  @redis = redis
  @namespace = namespace
  super()
end

Class Method Details

.set_latency(redis:, namespace:, at:, duration:) ⇒ Object

Set the latency.

Parameters:

  • redis (RedisClient::Common)

    Redis connection.

  • namespace (String)

    Key namespace.

  • at (Time, Integer)

    Time this record was taken.

  • duration (Numeric)

    Duration of the request in fractional seconds.



22
23
24
25
26
27
28
29
# File 'lib/amigo/autoscaler/checkers/web_latency.rb', line 22

def self.set_latency(redis:, namespace:, at:, duration:)
  bucket = at.to_i
  key = "#{namespace}/latencies:#{bucket}"
  duration_ms = (duration * 1000).round
  redis.call("HINCRBY", key, "count", 1)
  redis.call("HINCRBY", key, "sum", duration_ms)
  redis.call("EXPIRE", key, WINDOW + 1)
end

Instance Method Details

#get_latenciesObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/amigo/autoscaler/checkers/web_latency.rb', line 39

def get_latencies
  now = Time.now.to_i
  window = (now - (WINDOW - 1))..now
  keys = window.map { |bucket| "#{@namespace}/latencies:#{bucket}" }
  results = @redis.pipelined do |pipeline|
    keys.each do |k|
      pipeline.call("HMGET", k, "count", "sum")
    end
  end
  counts = 0
  sums = 0
  first_seen_bucket = nil
  last_seen_bucket = nil
  results.zip(window).each do |(count, sum), bucket|
    next unless count # No results for this bucket
    counts += count.to_i
    sums += sum.to_i
    first_seen_bucket ||= bucket
    last_seen_bucket = bucket
  end
  return {} if first_seen_bucket.nil? || counts.zero?
  return {} if (last_seen_bucket - first_seen_bucket) < MINIMUM_CONFIDENCE_WINDOW
  latency = sums.to_f / counts
  return {"web" => latency.to_f / 1000}
end

#get_pool_usageObject



37
# File 'lib/amigo/autoscaler/checkers/web_latency.rb', line 37

def get_pool_usage = nil