class RequestResponseStats::RedisRecord

Constants

ALERT_THRESHOLD
AT_ERROR_COUNT
AT_MAX_SWAP_MEMORY_MB
AT_MAX_TIME
PERMITTED_KEYS
REDIS_RR_KEY_NAMESPACE

Attributes

key[RW]
value[RW]

Public Class Methods

all_keys(opts={}) click to toggle source

returns all request_response_stats relevant redis keys by default only PUBLIC keys are returned

# File lib/request_response_stats/redis_record.rb, line 75
def all_keys(opts={})
  support = opts[:support] || false
  if support
    regex = /^#{REDIS_RR_KEY_NAMESPACE}/
  else
    regex = /^#{REDIS_RR_KEY_NAMESPACE}_PUBLIC/
  end

  redis.keys.select{|k| k =~ regex}.sort.reverse
end
del(key) click to toggle source

delete value from redis wrapper from redis' `del` method

# File lib/request_response_stats/redis_record.rb, line 69
def del(key)
  redis.del(key)
end
flush_all_keys() click to toggle source

flushes all request_response_stats data from redis

# File lib/request_response_stats/redis_record.rb, line 112
def flush_all_keys
  redis.del(*all_keys(support: true)) if all_keys.present?
end
formatted_parsed_get_for_mongo(key) click to toggle source

it returns parsed result into the format required for Mongo dump

# File lib/request_response_stats/redis_record.rb, line 92
def formatted_parsed_get_for_mongo(key)
  data = parsed_get(key)
  data["start_time"] = date_time_str_to_obj(data["start_time"])
  data["end_time"] = date_time_str_to_obj(data["end_time"])

  data
end
freezed_keys() click to toggle source

returns all PUBLIC request_response_stats related freezed keys from redis freezed key: redis key which will no longer be updated only freezed keys are eligible to be moved to mongo

# File lib/request_response_stats/redis_record.rb, line 163
def freezed_keys
  all_keys.map{|k| self.new(k)}.select{|k| k.is_key_freezed?}.map{|rr| rr.key}
end
get(key) click to toggle source

get value from redis wrapper from redis' `get` method

# File lib/request_response_stats/redis_record.rb, line 57
def get(key)
  redis.get(key)
end
get_slot_range_for_key(redis_key) click to toggle source
# File lib/request_response_stats/redis_record.rb, line 133
def get_slot_range_for_key(redis_key)
  date_slot_string = redis_key.split("_")[-1]

  get_slot_range_for_date_slot_string(date_slot_string)
end
group_stats_by_time_duration() click to toggle source

it has to be overridden

# File lib/request_response_stats/redis_record.rb, line 117
def group_stats_by_time_duration
  raise StandardError, "UNDEFINED #{__method__}"
end
hashify_all_data(opts={}) click to toggle source

returns collection of all relevant PUBLIC request_response_stats data from redis

# File lib/request_response_stats/redis_record.rb, line 101
def hashify_all_data(opts={})
  support = opts[:support] || false
  req_res_stat = ActiveSupport::HashWithIndifferentAccess.new
  all_keys(support: support).each do |key|
    req_res_stat[key] = ActiveSupport::HashWithIndifferentAccess.new(parsed_get key)
  end

  req_res_stat
end
jsonified_set(key, value, options={}, custom_options={strict_key_check: true}) click to toggle source

set jsonified value to redis and raise alerts

# File lib/request_response_stats/redis_record.rb, line 140
def jsonified_set(key, value, options={}, custom_options={strict_key_check: true})
  value.select!{|k,v| PERMITTED_KEYS.include? k.to_s} if custom_options[:strict_key_check]

  # set jsonified value to redis
  redis.set(key, value.to_json, options)

  # get alerts collection
  alerts = ALERT_THRESHOLD.select{ |k, v| value[k] >= v if value[k] }.map{|k,v| {
    redis_key: key,
    alarm_key: k,
    alarm_value: v,
    actual_value: value[k]
  }}
  alerts_data = {data: alerts}.to_json
  raise_alert(alerts_data) if alerts.present?

  # return alerts
  alerts_data
end
new(key, value=nil) click to toggle source
# File lib/request_response_stats/redis_record.rb, line 225
def initialize(key, value=nil)
  @key = key
  @value = value
end
parsed_get(key) click to toggle source

return parsed value from redis

# File lib/request_response_stats/redis_record.rb, line 87
def parsed_get(key)
  JSON.parse(redis.get(key) || "{}")
end
query(params={}) click to toggle source

lets you fetch records for given conditions from redis

# File lib/request_response_stats/redis_record.rb, line 168
def query(params={})
  # to implement
end
redis() click to toggle source

returns the redis connection this method must be redefined for `RedisRecord` to be useable

# File lib/request_response_stats/redis_record.rb, line 51
def redis
  raise StandardError, "UNDEFINED #{__method__}"
end
req_key(server_name, req_object_id) click to toggle source
# File lib/request_response_stats/redis_record.rb, line 125
def req_key(server_name, req_object_id)
  support_key(server_name, ["REQ_OBJ", req_object_id].join("_"))
end
req_res_key(server_name, api_name, api_http_verb) click to toggle source
# File lib/request_response_stats/redis_record.rb, line 129
def req_res_key(server_name, api_name, api_http_verb)
  ["#{REDIS_RR_KEY_NAMESPACE}_PUBLIC_#{server_name}_#{api_name}_#{api_http_verb}", get_time_slot_name].compact.join("_")
end
set(key, value, options={}) click to toggle source

set value to redis wrapper from redis' `set` method

# File lib/request_response_stats/redis_record.rb, line 63
def set(key, value, options={})
  redis.set(key, value, options)
end
support_key(server_name, key_name="default") click to toggle source
# File lib/request_response_stats/redis_record.rb, line 121
def support_key(server_name, key_name="default")
  [REDIS_RR_KEY_NAMESPACE, "SUPPORT", server_name.to_s, key_name].join("_")
end

Private Class Methods

date_time_str_to_obj(date_time_str) click to toggle source

Input example: “2017-11-06 09:01:00 UTC”

# File lib/request_response_stats/redis_record.rb, line 211
def date_time_str_to_obj(date_time_str)
  date, time, zone = date_time_str.split(" ")
  date = date.split("-").map(&:to_i)
  time = time.split(":").map(&:to_i)
  zone = "+00:00" if zone == ["UTC"]
  DateTime.new(*date, *time, zone)
end
get_slot_range_for_date_slot_string(date_slot_string) click to toggle source

returns time range of given date_slot_stringe which is [start_time_of_slot, end_time_of_slot]

# File lib/request_response_stats/redis_record.rb, line 197
def get_slot_range_for_date_slot_string(date_slot_string)
  year_num, month_num, date_num, slot_num = date_slot_string.split("-").map(&:to_i)
  time = Time.utc(year_num, month_num, date_num)

  # num_of_slots_in_a_day = 24.hours / group_stats_by_time_duration
  seconds_in_a_time_slot = group_stats_by_time_duration.seconds.to_i
  seconds_already_passed = slot_num * seconds_in_a_time_slot
  starting_time = time + seconds_already_passed
  ending_time = starting_time + seconds_in_a_time_slot

  [starting_time, ending_time]
end
get_time_slot_name(current_time = Time.now) click to toggle source

Example: for a value of `1.hour` for `group_stats_by_time_duration`, the data for each endpoint is divided into `1 day / 1.hour = 24` time slots within a day

# File lib/request_response_stats/redis_record.rb, line 176
def get_time_slot_name(current_time = Time.now)
  current_time_utc = current_time.utc
  seconds_since_beginning_of_today = (current_time_utc - Time.utc(current_time_utc.year, current_time_utc.month, current_time_utc.day)).to_i
  # seconds_in_a_day = 24 * 60 * 60
  num_of_slots_in_a_day = 24.hours / group_stats_by_time_duration
  seconds_in_a_time_slot = group_stats_by_time_duration.seconds.to_i
  current_slot = (seconds_since_beginning_of_today / seconds_in_a_time_slot).to_i
  slot_str_length = num_of_slots_in_a_day.to_s.size
  current_slot_name = "%0#{slot_str_length}d" % current_slot
  current_slot_full_name = [
    current_time_utc.year,
    "%02d" % current_time_utc.month,  # current_time_utc.month
    "%02d" % current_time_utc.day,  # current_time_utc.day
    current_slot_name
  ].join("-")

  current_slot_full_name
end
raise_alert(data) click to toggle source
# File lib/request_response_stats/redis_record.rb, line 219
def raise_alert(data)
  name.split("::")[0].constantize.custom_alert_code(data)
end

Public Instance Methods

is_key_freezed?() click to toggle source

if a key is freezed then no more data will be written to it

# File lib/request_response_stats/redis_record.rb, line 231
def is_key_freezed?
  return nil unless self.class.group_stats_by_time_duration

  self.class.get_slot_range_for_key(key)[1] < Time.now
end