Monitor Sidekiq cron jobs: server middleware ping on success and failure
A Sidekiq server middleware wraps yield in
begin/rescue: on success it GETs the ping URL; in rescue
it POSTs the exception text to /fail and re-raises.
Register it once in Sidekiq.configure_server to cover
every worker. Pair with sidekiq-cron for scheduled jobs.
Absence detection handles a down Sidekiq process. Free, no monitor cap.
Your assistant can do this for you
Monitor my Sidekiq jobs with LastPing
On this page
The snippets
Create a monitor in the console, set the schedule to match your sidekiq-cron expression plus a grace window, and copy the ping URL.
Global server middleware: covers all workers
Store the ping URL as a constant on the worker class so each
worker can have its own monitor. The middleware reads it via
worker.class::PING if defined, or falls back to a
default:
require 'net/http'
require 'uri'
module LastPingMiddleware
class Server
def call(worker, _job, _queue)
ping_url = worker.class.const_defined?(:PING) ?
worker.class::PING :
ENV['LASTPING_DEFAULT_URL']
return yield unless ping_url # skip unmonitored workers
begin
yield # run the job
Net::HTTP.get(URI(ping_url))
rescue => e
body = "#{e.class}: #{e.message}"[0, 10_000]
uri = URI("#{ping_url}/fail")
req = Net::HTTP::Post.new(uri)
req.body = body
Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
raise
end
end
end
end
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add LastPingMiddleware::Server
end
end
Worker with its own PING constant
Each worker declares PING as a constant. The
middleware picks it up automatically, so no additional
configuration is needed when you add a new monitored worker:
class DailyReportJob
include Sidekiq::Job
PING = "https://ping.lastping.dev/<your-monitor-id>"
def perform
# your job logic
generate_report
upload_to_s3
end
end
sidekiq-cron schedule
Register the cron schedule in an initializer or a YAML file. The middleware monitors the same job class regardless of whether it was enqueued manually or by the cron scheduler:
# config/initializers/sidekiq_cron.rb
require 'sidekiq-cron'
Sidekiq::Cron::Job.load_from_hash({
'daily_report' => {
'cron' => '0 2 * * *',
'class' => 'DailyReportJob',
},
'weekly_cleanup' => {
'cron' => '0 3 * * 1',
'class' => 'WeeklyCleanupJob',
},
})
Why re-raise matters here too
Re-raising after the /fail ping keeps Sidekiq's
built-in retry semantics intact. The job retries according to its
sidekiq_options retry: configuration, and Sidekiq's
dead-set captures it if all retries fail. The LastPing ping adds
fast alerting on top: it doesn't replace Sidekiq's error
handling. See also the
Ruby script monitoring guide for the
plain-script pattern and the
cron guide for OS-level scheduling.
AI agents can provision monitors via the
LastPing MCP server.
What this catches
The middleware reports what it can; the silence reports the rest.
- A Ruby exception in the job: middleware rescues, POSTs to
/fail, and re-raises so Sidekiq's retry logic still applies. - Successful job completion:
yieldreturns without raising; the success ping resets the absence timer. - Sidekiq process killed: in-flight jobs are lost; no success ping arrives; the absence opens the incident after the grace window.
- sidekiq-cron is down: no jobs are enqueued; absence → incident.
- Recovery: the next successful job run triggers the success ping, closing the incident automatically.
Questions people ask
Front-loaded answers: the most important fact first.
-
How do I monitor a Sidekiq cron job with LastPing?
Add a Sidekiq server middleware that wraps the
yieldcall in begin/rescue: on success GET the ping URL withNet::HTTP; in rescue POST the exception text to/failand re-raise. Register it inSidekiq.configure_server. -
Does the middleware run for every worker or just specific ones?
Server middleware runs for every job by default. To scope it to specific workers, store the ping URL in a
PINGconstant on the worker class so each worker can have its own monitor: the constant check gates which workers actually trigger a ping, and workers without the constant are skipped withreturn yield. You can also check the worker class inside the middleware usingworker.class.name. -
How does sidekiq-cron fit in?
sidekiq-cronschedules Sidekiq jobs on a cron expression. The jobs themselves run through the normal Sidekiq worker pipeline, so the middleware approach monitors them without any changes to the cron configuration. -
What if Sidekiq itself is down?
If Sidekiq is not running, no jobs are processed and no middleware fires. Absence-detection monitoring catches this: the missing ping after the grace window opens an incident, with no running Sidekiq process or worker required on the failure detection side.
-
Can I use Faraday instead of Net::HTTP in the middleware?
Yes. Any HTTP client works inside the middleware's call method. Faraday, HTTParty, or
Net::HTTPfrom the stdlib are all valid choices. The ping is a plain GET or POST. -
Is Sidekiq cron monitoring free?
Yes. LastPing is free for individuals with no monitor cap. See how it compares to Healthchecks.io and Cronitor.
Register once, cover every Sidekiq worker you'll ever add.
One middleware class now beats a silent background job later. First alert wired up in about a minute, and LastPing monitors itself the same way.