Class: RequestResponseStats::RedisRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/request_response_stats/redis_record.rb

Constant Summary collapse

REDIS_RR_KEY_NAMESPACE =
"api_req_res"
PERMITTED_KEYS =
[
  :key_name,
  :server_name,
  :api_name,
  :api_verb,
  :api_controller,
  :api_action,
  :request_count,
  :min_time,
  :max_time,
  :avg_time,
  :start_time,
  :end_time,
  :error_count,
  :min_used_memory_MB,
  :max_used_memory_MB,
  :avg_used_memory_MB,
  :min_swap_memory_MB,
  :max_swap_memory_MB,
  :avg_swap_memory_MB,
  :avg_gc_stat_diff,
  :min_gc_stat_diff,
  :max_gc_stat_diff,
].map(&:to_s)
AT_MAX_TIME =
nil
AT_ERROR_COUNT =
nil
AT_MAX_SWAP_MEMORY_MB =
nil
ALERT_THRESHOLD =
{
  max_time: AT_MAX_TIME || 30,
  error_count: AT_ERROR_COUNT || 2,
  max_swap_memory_MB: AT_MAX_SWAP_MEMORY_MB || 200,
}.stringify_keys

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, value = nil) ⇒ RedisRecord

Returns a new instance of RedisRecord.



225
226
227
228
# File 'lib/request_response_stats/redis_record.rb', line 225

def initialize(key, value=nil)
  @key = key
  @value = value
end

Instance Attribute Details

#keyObject

Returns the value of attribute key.



9
10
11
# File 'lib/request_response_stats/redis_record.rb', line 9

def key
  @key
end

#valueObject

Returns the value of attribute value.



9
10
11
# File 'lib/request_response_stats/redis_record.rb', line 9

def value
  @value
end

Class Method Details

.all_keys(opts = {}) ⇒ Object

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



75
76
77
78
79
80
81
82
83
84
# 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) ⇒ Object

delete value from redis wrapper from redis’ ‘del` method



69
70
71
# File 'lib/request_response_stats/redis_record.rb', line 69

def del(key)
  redis.del(key)
end

.flush_all_keysObject

flushes all request_response_stats data from redis



112
113
114
# 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) ⇒ Object

it returns parsed result into the format required for Mongo dump



92
93
94
95
96
97
98
# 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_keysObject

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



163
164
165
# 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) ⇒ Object

get value from redis wrapper from redis’ ‘get` method



57
58
59
# File 'lib/request_response_stats/redis_record.rb', line 57

def get(key)
  redis.get(key)
end

.get_slot_range_for_key(redis_key) ⇒ Object



133
134
135
136
137
# 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_durationObject

it has to be overridden

Raises:

  • (StandardError)


117
118
119
# 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 = {}) ⇒ Object

returns collection of all relevant PUBLIC request_response_stats data from redis



101
102
103
104
105
106
107
108
109
# 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}) ⇒ Object

set jsonified value to redis and raise alerts



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# 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

.parsed_get(key) ⇒ Object

return parsed value from redis



87
88
89
# File 'lib/request_response_stats/redis_record.rb', line 87

def parsed_get(key)
  JSON.parse(redis.get(key) || "{}")
end

.query(params = {}) ⇒ Object

lets you fetch records for given conditions from redis



168
169
170
# File 'lib/request_response_stats/redis_record.rb', line 168

def query(params={})
  # to implement
end

.redisObject

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

Raises:

  • (StandardError)


51
52
53
# File 'lib/request_response_stats/redis_record.rb', line 51

def redis
  raise StandardError, "UNDEFINED #{__method__}"
end

.req_key(server_name, req_object_id) ⇒ Object



125
126
127
# 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) ⇒ Object



129
130
131
# 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 = {}) ⇒ Object

set value to redis wrapper from redis’ ‘set` method



63
64
65
# 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") ⇒ Object



121
122
123
# 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

Instance Method Details

#is_key_freezed?Boolean

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

Returns:

  • (Boolean)


231
232
233
234
235
# 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