class Yabeda::Latency::Collector

Collector is a Rack middleware that provides meaures the latency of an HTTP request based on the “X-Request-Start” header.

By default metrics all have the prefix “http_server”. Set `:metrics_prefix` to something else if you like.

Attributes

app[R]
registry[R]

Public Class Methods

new(app, metrics_prefix: :http_server, debug: false) click to toggle source
# File lib/yabeda/latency/collector.rb, line 17
def initialize(app, metrics_prefix: :http_server, debug: false)
  @app = app
  @metrics_prefix = metrics_prefix
  @debug = debug

  init_request_metrics
end

Protected Instance Methods

calculate_latency_seconds(env, now) click to toggle source
# File lib/yabeda/latency/collector.rb, line 71
def calculate_latency_seconds(env, now)
  raw_header_value = env[REQUEST_START_HEADER]
  request_start_timestamp_s = extract_timestamp_from_header_value(raw_header_value)

  puts "X-Request-Start: #{raw_header_value}, Now: #{now.to_f}" if @debug

  return unless request_start_timestamp_s

  now.to_f - request_start_timestamp_s
end
extract_timestamp_from_header_value(value) click to toggle source
# File lib/yabeda/latency/collector.rb, line 82
def extract_timestamp_from_header_value(value)
  return unless value

  str = case value
        when /^\s*([\d+.]+)\s*$/ then Regexp.last_match(1)
        # following regexp intentionally unanchored to handle
        # (ie ignore) leading server names
        when /t=([\d+.]+)/       then Regexp.last_match(1) # rubocop:disable Lint/DuplicateBranch
        end

  return unless str

  str.to_f
end
init_request_metrics() click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/yabeda/latency/collector.rb, line 43
def init_request_metrics
  prefix = @metrics_prefix

  Yabeda.configure do
    group prefix do
      histogram(
        :request_latency,
        comment: 'The time for the HTTP request to reach Rack application',
        unit: :seconds,
        per: :field,
        tags: [],
        buckets: LATENCY_BUCKETS
      )
    end
  end
end
measure(latency_seconds) click to toggle source
# File lib/yabeda/latency/collector.rb, line 65
def measure(latency_seconds)
  return if latency_seconds.negative? # sanity check

  metric.measure(EMPTY_HASH, latency_seconds)
end
metric() click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/yabeda/latency/collector.rb, line 61
def metric
  @metric ||= Yabeda.__send__(@metrics_prefix).request_latency
end
observe(env, now) click to toggle source
# File lib/yabeda/latency/collector.rb, line 35
def observe(env, now)
  latency_seconds = calculate_latency_seconds(env, now)
  measure(latency_seconds) unless latency_seconds.nil?
rescue StandardError => e
  warn "Could not observe latency (#{e.message})" if @debug
end