mirror of
https://github.com/SrIzan10/hc-harbor.git
synced 2026-05-01 10:45:21 +00:00
Add rps tracker to footer (#364)
This commit is contained in:
@@ -3,6 +3,7 @@ class ApplicationController < ActionController::Base
|
||||
before_action :honeybadger_context, if: :current_user
|
||||
before_action :initialize_cache_counters
|
||||
before_action :try_rack_mini_profiler_enable
|
||||
before_action :track_request
|
||||
after_action :track_action
|
||||
|
||||
around_action :switch_time_zone, if: :current_user
|
||||
@@ -30,6 +31,10 @@ class ApplicationController < ActionController::Base
|
||||
ahoy.track "Ran action", request.path_parameters
|
||||
end
|
||||
|
||||
def track_request
|
||||
RequestCounter.increment
|
||||
end
|
||||
|
||||
def try_rack_mini_profiler_enable
|
||||
if current_user && current_user.is_admin?
|
||||
Rack::MiniProfiler.authorize_request
|
||||
|
||||
@@ -5,6 +5,11 @@ module ApplicationHelper
|
||||
{ hits: hits, misses: misses }
|
||||
end
|
||||
|
||||
def requests_per_second
|
||||
rps = RequestCounter.per_second
|
||||
rps == :high_load ? "lots of req/sec" : "#{rps} req/sec"
|
||||
end
|
||||
|
||||
def admin_tool(class_name = "", element = "div", **options, &block)
|
||||
return unless current_user&.is_admin?
|
||||
concat content_tag(element, class: "admin-tool #{class_name}", **options, &block)
|
||||
|
||||
57
app/lib/request_counter.rb
Normal file
57
app/lib/request_counter.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
class RequestCounter
|
||||
WINDOW_SIZE = 10 # seconds - shorter window for more responsive rates
|
||||
HIGH_LOAD_THRESHOLD = 500 # req/sec to disable tracking
|
||||
CIRCUIT_BREAKER_DURATION = 30 # seconds to stay disabled
|
||||
|
||||
@buckets = {}
|
||||
@disabled_until = nil
|
||||
|
||||
class << self
|
||||
def increment
|
||||
return if disabled?
|
||||
|
||||
current_time = Time.current.to_i
|
||||
@buckets[current_time] = (@buckets[current_time] || 0) + 1
|
||||
|
||||
# Check if we should disable due to high load
|
||||
check_circuit_breaker(current_time)
|
||||
|
||||
# Periodically clean old buckets (1% chance)
|
||||
cleanup if rand(100) == 0
|
||||
end
|
||||
|
||||
def per_second
|
||||
return :high_load if disabled?
|
||||
|
||||
current_time = Time.current.to_i
|
||||
cutoff = current_time - WINDOW_SIZE
|
||||
|
||||
total = @buckets.select { |timestamp, _| timestamp >= cutoff }.values.sum
|
||||
(total.to_f / WINDOW_SIZE).round(2)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def disabled?
|
||||
@disabled_until && Time.current.to_i < @disabled_until
|
||||
end
|
||||
|
||||
def check_circuit_breaker(current_time)
|
||||
# Check last 5 seconds for high load
|
||||
recent_total = @buckets.select { |ts, _| ts >= current_time - 5 }.values.sum
|
||||
|
||||
if recent_total > HIGH_LOAD_THRESHOLD * 5 # 5 seconds worth
|
||||
@disabled_until = current_time + CIRCUIT_BREAKER_DURATION
|
||||
@buckets.clear # Clear to reduce memory
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
return if disabled? # Skip cleanup when disabled
|
||||
|
||||
current_time = Time.current.to_i
|
||||
cutoff = current_time - WINDOW_SIZE - 10 # extra buffer
|
||||
@buckets.reject! { |timestamp, _| timestamp < cutoff }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -168,6 +168,7 @@
|
||||
in the last 24 hours.
|
||||
(DB: <%= pluralize(QueryCount::Counter.counter, "query") %>, <%= QueryCount::Counter.counter_cache %> cached)
|
||||
(CACHE: <%= cache_stats[:hits] %> hits, <%= cache_stats[:misses] %> misses)
|
||||
(<%= requests_per_second %>)
|
||||
</p>
|
||||
<% if session[:impersonater_user_id] %>
|
||||
<%= link_to "Stop impersonating", stop_impersonating_path, class: "impersonate-link", data: { turbo_prefetch: "false" } %>
|
||||
|
||||
Reference in New Issue
Block a user