Skip to content

Instantly share code, notes, and snippets.

@jgaskins
Last active May 16, 2024 13:12
Show Gist options
  • Save jgaskins/8fa816a78dc15b7c210fb0503b9ab1ff to your computer and use it in GitHub Desktop.
Save jgaskins/8fa816a78dc15b7c210fb0503b9ab1ff to your computer and use it in GitHub Desktop.
Rack request stats
#!/usr/bin/env ruby
%w(lib shared).each do |dir|
$LOAD_PATH.unshift(__dir__) unless $LOAD_PATH.include?(__dir__)
end
Gem::Specification.new do |spec|
spec.name = "rack-request_stats"
spec.version = "0.1.0"
spec.authors = ["Jamie Gaskins"]
spec.email = ["jgaskins@hey.com"]
spec.summary = %q{Rack middleware to log request stats}
spec.description = spec.summary
spec.homepage = "https://gist.github.com/jgaskins/8fa816a78dc15b7c210fb0503b9ab1ff"
spec.license = "MIT"
spec.files = Dir["*.rb"]
spec.executables = []
spec.test_files = []
spec.require_paths = ["."]
spec.add_runtime_dependency "rack"
end
require "rack"
require "logger"
require "thread"
class Rack::RequestStats
VERSION = "0.1.0"
attr_reader :logger
Stats = Struct.new(:count, :requests_per_sec, :concurrent, keyword_init: true)
def initialize(app, logger: Logger.new(STDOUT, level: Logger::INFO), log_every: nil, start_immediately: true)
@app = app
@logger = logger
@count = 0
@concurrent = 0
@mutex = Mutex.new
@log_every = if (log_every = log_every.to_i) == 0
1
else
log_every
end
mark_last!
start if start_immediately
end
def call(env)
sync do
@count += 1
@concurrent += 1
end
@app.call env
ensure
sync { @concurrent -= 1 }
end
def start
Thread.new do
loop do
sleep @log_every
@logger.info stats
rescue ex
@logger.error ex.message
end
end
end
def stats
last = sync { @last.tap { mark_last! } }
stats = Stats.new(
count: @count,
requests_per_sec: @count.to_f / (@last - last),
concurrent: @concurrent,
)
@count = 0
stats
end
private def sync
@mutex.synchronize { yield }
end
private def mark_last!
@last = timestamp
end
private def timestamp
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
end
@LeipeLeon
Copy link

TIL: you can create a gem in a gist 🎉

usage: gem "rack-request_stats", gist: "jgaskins/8fa816a78dc15b7c210fb0503b9ab1ff"

@jgaskins
Copy link
Author

Indeed. In fact, I’m even the one that added it to Bundler. 😄 rubygems/bundler@a3a3efa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment