Files
MySMSAPio/app/models/concerns/metrics.rb
2025-10-22 17:22:17 +08:00

82 lines
2.0 KiB
Ruby

module Metrics
extend ActiveSupport::Concern
class_methods do
def increment_counter(metric_name, amount = 1)
cache_key = "metrics:#{metric_name}"
current_value = Rails.cache.read(cache_key) || 0
Rails.cache.write(cache_key, current_value + amount)
end
def decrement_counter(metric_name, amount = 1)
cache_key = "metrics:#{metric_name}"
current_value = Rails.cache.read(cache_key) || 0
new_value = [current_value - amount, 0].max
Rails.cache.write(cache_key, new_value)
end
def get_counter(metric_name)
cache_key = "metrics:#{metric_name}"
Rails.cache.read(cache_key) || 0
end
def reset_counter(metric_name)
cache_key = "metrics:#{metric_name}"
Rails.cache.delete(cache_key)
end
def set_gauge(metric_name, value)
cache_key = "metrics:gauge:#{metric_name}"
Rails.cache.write(cache_key, value)
end
def get_gauge(metric_name)
cache_key = "metrics:gauge:#{metric_name}"
Rails.cache.read(cache_key)
end
# Record timing metrics
def record_timing(metric_name, duration_ms)
cache_key = "metrics:timing:#{metric_name}"
timings = Rails.cache.read(cache_key) || []
timings << duration_ms
# Keep only last 100 measurements
timings = timings.last(100)
Rails.cache.write(cache_key, timings)
end
def get_timing_stats(metric_name)
cache_key = "metrics:timing:#{metric_name}"
timings = Rails.cache.read(cache_key) || []
return nil if timings.empty?
{
count: timings.size,
avg: timings.sum / timings.size.to_f,
min: timings.min,
max: timings.max,
p95: percentile(timings, 95),
p99: percentile(timings, 99)
}
end
private
def percentile(array, percent)
return nil if array.empty?
sorted = array.sort
k = (percent / 100.0) * (sorted.length - 1)
f = k.floor
c = k.ceil
if f == c
sorted[k]
else
sorted[f] * (c - k) + sorted[c] * (k - f)
end
end
end
end