Class: RailsOrbit::Metric

Inherits:
ApplicationRecord show all
Defined in:
app/models/rails_orbit/metric.rb

Class Method Summary collapse

Class Method Details

.bucketed_hit_rate_series(since:, bucket_minutes:) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/models/rails_orbit/metric.rb', line 65

def self.bucketed_hit_rate_series(since:, bucket_minutes:)
  conn    = connection
  seconds = bucket_minutes * 60
  bucket  = bucket_expression(seconds)
  q_since = conn.quote(since.utc.strftime("%Y-%m-%d %H:%M:%S"))
  q_hit   = conn.quote("solid_cache.read_hit")
  q_miss  = conn.quote("solid_cache.read_miss")

  sql = "SELECT #{bucket} AS bucket, " \
        "SUM(CASE WHEN key = #{q_hit} THEN value ELSE 0 END) AS hits, " \
        "SUM(CASE WHEN key = #{q_miss} THEN value ELSE 0 END) AS misses " \
        "FROM #{conn.quote_table_name(table_name)} " \
        "WHERE key IN (#{q_hit}, #{q_miss}) AND recorded_at >= #{q_since} " \
        "GROUP BY bucket ORDER BY bucket"

  conn.select_all(sql).rows.map do |row|
    { t: row[0].to_s, v: hit_rate(row[1].to_f, row[2].to_f) }
  end
end

.bucketed_series(key, since:, bucket_minutes:, aggregate: :sum) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/models/rails_orbit/metric.rb', line 51

def self.bucketed_series(key, since:, bucket_minutes:, aggregate: :sum)
  conn    = connection
  seconds = bucket_minutes * 60
  agg_fn  = aggregate == :avg ? "AVG" : "SUM"
  bucket  = bucket_expression(seconds)

  sql = "SELECT #{bucket} AS bucket, #{agg_fn}(value) AS val " \
        "FROM #{conn.quote_table_name(table_name)} " \
        "WHERE key = #{conn.quote(key)} AND recorded_at >= #{conn.quote(since.utc.strftime('%Y-%m-%d %H:%M:%S'))} " \
        "GROUP BY bucket ORDER BY bucket"

  conn.select_all(sql).rows.map { |row| { t: row[0].to_s, v: row[1].to_f.round(1) } }
end

.compute_delta(key, window:) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
# File 'app/models/rails_orbit/metric.rb', line 25

def self.compute_delta(key, window:)
  now      = Time.current
  current  = where(recorded_at: (now - window)..now).for_key(key).sum(:value).to_i
  previous = where(recorded_at: (now - window * 2)..(now - window)).for_key(key).sum(:value).to_i
  return { value: 0, direction: :flat } if previous.zero? && current.zero?
  return { value: 100, direction: :up } if previous.zero?

  pct = (((current - previous).to_f / previous) * 100).round(0)
  direction = pct.positive? ? :up : (pct.negative? ? :down : :flat)
  { value: pct.abs, direction: direction }
end

.compute_hit_rate_delta(window:) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/rails_orbit/metric.rb', line 37

def self.compute_hit_rate_delta(window:)
  now = Time.current
  cur_hits   = where(recorded_at: (now - window)..now).for_key("solid_cache.read_hit").sum(:value).to_f
  cur_misses = where(recorded_at: (now - window)..now).for_key("solid_cache.read_miss").sum(:value).to_f
  prev_hits   = where(recorded_at: (now - window * 2)..(now - window)).for_key("solid_cache.read_hit").sum(:value).to_f
  prev_misses = where(recorded_at: (now - window * 2)..(now - window)).for_key("solid_cache.read_miss").sum(:value).to_f

  cur_rate  = hit_rate(cur_hits, cur_misses)
  prev_rate = hit_rate(prev_hits, prev_misses)
  diff = (cur_rate - prev_rate).round(1)
  direction = diff.positive? ? :up : (diff.negative? ? :down : :flat)
  { value: diff.abs, direction: direction }
end

.hit_rate(hits, misses) ⇒ Object



16
17
18
19
# File 'app/models/rails_orbit/metric.rb', line 16

def self.hit_rate(hits, misses)
  total = hits.to_f + misses.to_f
  total.zero? ? 0.0 : ((hits / total) * 100).round(1)
end

.record(key:, value:, dimension: nil, at: Time.current) ⇒ Object



12
13
14
# File 'app/models/rails_orbit/metric.rb', line 12

def self.record(key:, value:, dimension: nil, at: Time.current)
  create!(key: key, value: value, dimension: dimension, recorded_at: at)
end

.sums_since(time) ⇒ Object



21
22
23
# File 'app/models/rails_orbit/metric.rb', line 21

def self.sums_since(time)
  since(time).group(:key).sum(:value)
end