{"id":13747485,"url":"https://github.com/socialpandas/sidekiq_monitor","last_synced_at":"2025-05-09T08:33:19.007Z","repository":{"id":56895537,"uuid":"8463019","full_name":"socialpandas/sidekiq_monitor","owner":"socialpandas","description":"Advanced monitoring for Sidekiq","archived":false,"fork":false,"pushed_at":"2015-05-07T15:26:36.000Z","size":933,"stargazers_count":230,"open_issues_count":14,"forks_count":36,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-04-27T09:41:08.464Z","etag":null,"topics":["histogram","message-queue","monitoring","ruby","sidekiq","sidekiq-monitor"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/socialpandas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-02-27T19:03:30.000Z","updated_at":"2024-03-28T10:57:47.000Z","dependencies_parsed_at":"2022-08-21T01:20:41.616Z","dependency_job_id":null,"html_url":"https://github.com/socialpandas/sidekiq_monitor","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socialpandas%2Fsidekiq_monitor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socialpandas%2Fsidekiq_monitor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socialpandas%2Fsidekiq_monitor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socialpandas%2Fsidekiq_monitor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/socialpandas","download_url":"https://codeload.github.com/socialpandas/sidekiq_monitor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224849267,"owners_count":17380083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["histogram","message-queue","monitoring","ruby","sidekiq","sidekiq-monitor"],"created_at":"2024-08-03T06:01:30.859Z","updated_at":"2024-11-15T21:30:33.583Z","avatar_url":"https://github.com/socialpandas.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"Sidekiq Monitor\n===============\nAdvanced monitoring for Sidekiq\n\nDescription\n-----------\nSidekiq Monitor offers a detailed UI for monitoring Sidekiq jobs, letting you filter, search, and sort jobs by many attributes, view error backtraces, set job completion metadata, and more.\n\nIt lets you:\n\n  * Sort jobs by:\n    * Queue\n    * Class\n    * Queued at time\n    * Started at time\n    * Duration\n    * Status (e.g. queued, running, complete, failed)\n  * Filter jobs by:\n    * Queue\n    * Class\n    * Status\n  * Set and view metadata for each job:\n    * Name - A customizable, human-readable name (e.g. 'Data Import for John Doe')\n    * Result - A customizable value describing the job's result (e.g. '{imported\\_documents\\_count: 241, imported\\_contacts_count: 183}')\n  * View errors for failed jobs, including a backtrace\n  * Easily isolate long-running jobs and failed jobs\n  * Retry failed jobs via a button-click\n\nAnd it looks like this:\n\n[\u003cimg src=\"https://raw.github.com/socialpandas/sidekiq_monitor/master/examples/screenshot_jobs.png\" /\u003e](https://raw.github.com/socialpandas/sidekiq_monitor/master/examples/screenshot.png)\n\nIt also includes a live, stacked histogram showing the health of each queue:\n\n[\u003cimg src=\"https://raw.github.com/socialpandas/sidekiq_monitor/master/examples/screenshot_graph.png\" /\u003e](https://raw.github.com/socialpandas/sidekiq_monitor/master/examples/screenshot.png)\n\nSidekiq Monitor stores jobs using ActiveRecord, allowing you to perform complex queries and delete specific collections of jobs:\n\n```ruby\nSidekiq::Monitor::Job.where(queue: 'user_update').where('enqueued_at \u003e ?', 2.days.ago).destroy_all\n```\n\nInstallation\n------------\n\nAdd sidekiq_monitor to your Gemfile:\n\n    gem 'sidekiq_monitor'\n\nInstall and run the migration:\n\n    rails g sidekiq:monitor:install\n    rake db:migrate\n\nMount it at a customizable path in `routes.rb`:\n\n    mount Sidekiq::Monitor::Engine =\u003e '/sidekiq'\n\nUsage\n-----\n\n### Setting a Job Name\n\nTo set a job's name (which makes the job's representation in the UI more human-readable), define a `self.job_name` method on your worker that takes the same arguments as its `perform` method:\n\n```ruby\nclass HardWorker\n  include Sidekiq::Worker\n\n  def perform(user_id)\n    puts 'Doing hard work'\n  end\n\n  def self.job_name(user_id)\n    User.find(user_id).username\n  end\nend\n```\n\n### Setting a Job Result\n\nTo set a job's result (which can show what the job accomplished, for example), return a hash from the worker's `perform` method:\n\n```ruby\nclass HardWorker\n  include Sidekiq::Worker\n\n  def perform(user_ids)\n    puts 'Doing hard work'\n    {\n      message: \"#{user_ids.length} users processed\",\n      processed_users_count: user_ids.length\n    }\n  end\nend\n```\n\nIf you set `:message` as a key of this hash, that value will be displayed in the Result column of jobs tables in the UI. To view the full result hash of a job in the UI, click on the job status button to open up the modal job view.\n\n### Graph\n\nA single histogram will be shown by default in the Graph view, but you can also split the queues into multiple histograms. (This is especially useful if you have a large number of queues and the single histogram has too many bars to be readable.) The keys of this hash are JS regex patterns for matching queues, and the values of the hash will be the titles of each histogram:\n\n```ruby\n# config/initializers/sidekiq_monitor.rb\nSidekiq::Monitor.options[:graphs] = {\n  'ALL' =\u003e 'All',\n  'OTHER' =\u003e 'Default Priority',\n  '_high$' =\u003e 'High Priority',\n  '_low$' =\u003e 'Low Priority'\n}\n```\n\n`ALL` and `OTHER` are special keys: `ALL` will show all queues and `OTHER` will show all queues that aren't matched by the regex keys.\n\n#### Poll Interval\n\nThe UI uses polling to update its data. By default, the polling interval is 3000ms, but you can adjust this like so:\n\n```ruby\n# config/initializers/sidekiq_monitor.rb\nSidekiq::Monitor.options[:poll_interval] = 5000\n```\n\n### UI Customization\n\n#### Custom Statuses\n\nThe UI's status filter and histograms show the most common job statuses, but if you'd like to add additional statuses to them (for example, if you want to show \"interrupted\" jobs or have added custom statuses through middleware), you can make the UI include them like so:\n\n```ruby\n# config/initializers/sidekiq_monitor.rb\nSidekiq::Monitor::Job.add_status('interrupted')\n```\n\n#### Custom Job Views\n\nWhen you click on a job, a modal showing its properties is displayed. You can add subviews to this modal by creating a view in your app and calling `Sidekiq::Monitor::CustomViews.add`, passing it the subview's title, the subview's filepath, and a block. The subview is only rendered if the block evaluates to true for the given job.\n\nIf you need to add JavaScript for the subview, you can do so by adding an asset path to `Sidekiq::Monitor.options[:javascripts]`.\n\nFor example, the following code adds a subview that shows a \"Retry\" button for jobs with the specified statuses:\n\n```ruby\n# config/initializers/sidekiq_monitor.rb\nview_path = Rails.root.join('app', 'views', 'sidekiq', 'monitor', 'retry').to_s\nSidekiq::Monitor::CustomViews.add('My View Title', view_path) do |job|\n  %w{complete failed}.include?(job.status)\nend\nSidekiq::Monitor.options[:javascripts] \u003c\u003c 'sidekiq/monitor/retry'\n```\n\n```\n/ app/views/sidekiq/monitor/retry.slim\na class='btn btn-success' href='#' data-action='retry_job' data-job-id=job.id = 'Retry'\n```\n\n```coffee\n# app/assets/javascripts/sidekiq/monitor/retry.js.coffee\n$ -\u003e\n  $('body').on 'click', '.job-modal [data-action=retry_job]', (e) -\u003e\n    id = $(e.target).attr('data-job-id')\n    $.get SidekiqMonitor.settings.api_url(\"jobs/retry/#{id}\")\n    alert 'Job has been retried'\n    false\n```\n\n### Authentication\n\nYou'll likely want to restrict access to this interface in a production setting. To do this, you can use routing constraints:\n\n#### Devise\n\nChecks a `User` model instance that responds to `admin?`\n\n```ruby\nconstraint = lambda { |request| request.env[\"warden\"].authenticate? and request.env['warden'].user.admin? }\nconstraints constraint do\n  mount Sidekiq::Monitor::Engine =\u003e '/sidekiq'\nend\n```\n\nAllow any authenticated `User`\n\n```ruby\nconstraint = lambda { |request| request.env['warden'].authenticate!({ scope: :user }) }\nconstraints constraint do\n  mount Sidekiq::Monitor::Engine =\u003e '/sidekiq'\nend\n```\n\nShort version\n\n```ruby\nauthenticate :user do\n  mount Sidekiq::Monitor::Engine =\u003e '/sidekiq'\nend\n```\n\n#### Authlogic\n\n```ruby\n# lib/admin_constraint.rb\nclass AdminConstraint\n  def matches?(request)\n    return false unless request.cookies['user_credentials'].present?\n    user = User.find_by_persistence_token(request.cookies['user_credentials'].split(':')[0])\n    user \u0026\u0026 user.admin?\n  end\nend\n\n# config/routes.rb\nrequire \"admin_constraint\"\nmount Sidekiq::Monitor::Engine =\u003e '/sidekiq', :constraints =\u003e AdminConstraint.new\n```\n\n#### Restful Authentication\n\nChecks a `User` model instance that responds to `admin?`\n\n```\n# lib/admin_constraint.rb\nclass AdminConstraint\n  def matches?(request)\n    return false unless request.session[:user_id]\n    user = User.find request.session[:user_id]\n    user \u0026\u0026 user.admin?\n  end\nend\n\n# config/routes.rb\nrequire \"admin_constraint\"\nmount Sidekiq::Monitor::Engine =\u003e '/sidekiq', :constraints =\u003e AdminConstraint.new\n```\n\n#### Custom External Authentication\n\n```ruby\nclass AuthConstraint\n  def self.admin?(request)\n    return false unless (cookie = request.cookies['auth'])\n\n    Rails.cache.fetch(cookie['user'], :expires_in =\u003e 1.minute) do\n      auth_data = JSON.parse(Base64.decode64(cookie['data']))\n      response = HTTParty.post(Auth.validate_url, :query =\u003e auth_data)\n\n      response.code == 200 \u0026\u0026 JSON.parse(response.body)['roles'].to_a.include?('Admin')\n    end\n  end\nend\n\n# config/routes.rb\nconstraints lambda {|request| AuthConstraint.admin?(request) } do\n  mount Sidekiq::Monitor::Engine =\u003e '/admin/sidekiq'\nend\n```\n\n_(This authentication documentation was borrowed from the [Sidekiq wiki](https://github.com/mperham/sidekiq/wiki/Monitoring).)_\n\nLicense\n-------\n\nSidekiq Monitor is released under the MIT License. Please see the MIT-LICENSE file for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocialpandas%2Fsidekiq_monitor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsocialpandas%2Fsidekiq_monitor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocialpandas%2Fsidekiq_monitor/lists"}