module LogStats
Puma plugin to log server stats whenever the number of concurrent requests exceeds a configured threshold.
Constants
- STAT_METHODS
Attributes
backtrace_filter[RW]
Proc to filter backtraces.
interval[RW]
Interval between logging attempts in seconds.
threshold[RW]
Minimum concurrent requests per process that will trigger logging server stats, or nil to disable logging. Default is the max number of threads in the server's thread pool. If this attribute is a Proc, it will be re-evaluated each interval.
Public Instance Methods
log(str)
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 63 def log(str) launcher.events.log str end
server()
click to toggle source
Save reference to Server object from the thread-local key.
# File lib/puma/plugin/log_stats.rb, line 68 def server @server ||= Thread.list.map { |t| t[Puma::Server::ThreadLocalKey] }.compact.first end
server_stats()
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 73 def server_stats STAT_METHODS.select(&server.method(:respond_to?)) .map { |name| [name, server.send(name) || 0] }.to_h end
should_log?()
click to toggle source
True if current server load meets configured threshold.
# File lib/puma/plugin/log_stats.rb, line 79 def should_log? threshold = LogStats.threshold threshold = threshold.call if threshold.is_a?(Proc) threshold = server.max_threads if threshold == :max threshold && (server.max_threads - server.pool_capacity) >= threshold end
start(launcher)
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 30 def start(launcher) @launcher = launcher launcher.events.register(:state) do |state| @state = state stats_logger_thread if state == :running end end
stats_logger_loop()
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 49 def stats_logger_loop sleep LogStats.interval return unless server if should_log? stats = server_stats stats[:threads] = thread_backtraces stats[:gc] = GC.stat log stats.to_json end rescue StandardError => e log "LogStats failed: #{e}\n #{e.backtrace.join("\n ")}" end
stats_logger_thread()
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 40 def stats_logger_thread Thread.new do if Thread.current.respond_to?(:name=) Thread.current.name = 'puma stats logger' end stats_logger_loop while @state == :running end end
thread_backtraces()
click to toggle source
# File lib/puma/plugin/log_stats.rb, line 86 def thread_backtraces worker_threads.map do |t| name = t.respond_to?(:name) ? t.name : thread.object_id.to_s(36) [name, LogStats.backtrace_filter.call(t.backtrace)] end.sort.to_h end
worker_threads()
click to toggle source
List all non-idle worker threads in the thread pool.
# File lib/puma/plugin/log_stats.rb, line 94 def worker_threads server.instance_variable_get(:@thread_pool) .instance_variable_get(:@workers) .reject { |t| t.backtrace.first.match?(/thread_pool\.rb.*sleep/) } end