Skip to content

Instantly share code, notes, and snippets.

@serverwentdown
Last active January 5, 2023 06:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save serverwentdown/b92e8fc688e24f1b54df822be770bb5b to your computer and use it in GitHub Desktop.
Save serverwentdown/b92e8fc688e24f1b54df822be770bb5b to your computer and use it in GitHub Desktop.
Munin Sidekiq plugin. Requires `perl-redis`. Install as `sidekiq_APP_NAME`
#!/usr/bin/perl -w
=head1 NAME
sidekiq - Get Sidekiq queue statistics from a Redis node
=head1 APPLICABLE SYSTEMS
Any Redis host with a Sidekiq application
=head1 CONFIGURATION
[sidekiq_redis1]
env.server 127.0.0.1:6379
env.key_prefix namespace:
[sidekiq_redis2]
env.server 127.0.0.2:6379
env.password password
env.key_prefix other-namespace:
env.database 1
=head1 MAGIC MARKERS
#%# family=auto
#%# capabilities=autoconf
=head1 BUGS
None known
=head1 LICENSE
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 dated June,
1991.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
=cut
use warnings;
use strict;
use Munin::Plugin;
use Redis;
# Check that multigraph is available
need_multigraph();
# Get the script name
my $plugin_name = $Munin::Plugin::me;
# Get the instance name
my $name;
if ($plugin_name =~ /sidekiq_(.+)*$/) {
$name = $1;
} else {
exit 1;
}
# Redis connection configuration
my $key_prefix = $ENV{'key_prefix'} || '';
sub sscan_all {
my ($redis, $key) = @_;
my $cursor = 0;
my @elements = ();
do {
my @result = $redis->sscan($key, $cursor);
$cursor = $result[0];
push(@elements, @{$result[1]});
} while ($cursor != 0);
return @elements;
}
sub redis_connect {
#
# Set up connection
#
my $redis = Redis->new(
server => $ENV{'server'} || '127.0.0.1:6379',
password => $ENV{'password'} || undef,
);
$redis->select($ENV{'database'} || 0);
return $redis;
}
if (defined($ARGV[0])) {
if ($ARGV[0] eq 'autoconf') {
#
# Test connection
#
my $redis_test = redis_connect();
print "yes\n";
$redis_test->quit();
exit 0;
}
if ($ARGV[0] eq 'config') {
my $redis = redis_connect();
#
# List all queues
#
my @queues = sscan_all($redis, "${key_prefix}queues");
print "multigraph ${plugin_name}_queues\n";
foreach my $queue (@queues) {
my $field = clean_fieldname($queue);
print "${field}.label ${queue}\n";
}
# Queue breakdown graph
print "multigraph ${plugin_name}_queues\n";
print "graph_title Sidekiq task queues ($name)\n";
print "graph_args --base 1000 --lower-limit 0\n";
print "graph_vlabel tasks in queue\n";
print "graph_scale no\n";
print "graph_category sidekiq\n";
#print "graph_total Total\n";
# Queue graph
print "multigraph ${plugin_name}_queue\n";
print "graph_title Sidekiq task activity ($name)\n";
print "graph_args --base 1000 --lower-limit 0\n";
print "graph_vlabel tasks in status\n";
print "graph_scale no\n";
print "graph_category sidekiq\n";
#print "graph_total Total\n";
print "queue.label Enqueued\n";
print "queue.info Total number of tasks waiting in queues\n";
print "busy.label Busy\n";
print "busy.info Tasks currently being processed\n";
print "schedule.label Scheduled\n";
print "schedule.info Tasks to be run in the future\n";
print "retry.label Retries\n";
print "retry.info Failed tasks that will be retried in the future\n";
print "dead.label Dead\n";
print "dead.info Failed tasks that will not be retried\n";
# Counter graph
print "multigraph ${plugin_name}_count\n";
print "graph_title Sidekiq processed and failed tasks ($name)\n";
print "graph_args --base 1000 --lower-limit 0\n";
print "graph_vlabel tasks / minute\n";
print "graph_scale no\n";
print "graph_category sidekiq\n";
print "graph_period minute\n";
print "processed.type DERIVE\n";
print "processed.min 0\n";
print "processed.label Processed\n";
print "processed.info Tasks sucessfully completed\n";
print "failed.type DERIVE\n";
print "failed.min 0\n";
print "failed.label Failed\n";
print "failed.info Errors raised by failed jobs\n";
exit 0;
}
}
my $redis = redis_connect();
#
# Sum the length of all queues, while also doing a per-queue breakdown
#
my @queues = sscan_all($redis, "${key_prefix}queues");
my $count_queue = 0;
print "multigraph ${plugin_name}_queues\n";
foreach my $queue (@queues) {
$redis->llen("${key_prefix}queue:${queue}", sub {
my $field = clean_fieldname($queue);
print "${field}.value $_[0]\n";
$count_queue += $_[0];
});
}
$redis->wait_all_responses;
#
# Sum the length of all processes
#
my @processes = sscan_all($redis, "${key_prefix}processes");
my $count_busy = 0;
foreach my $process (@processes) {
$redis->hget("${key_prefix}${process}", "busy", sub {
$count_busy += $_[0];
});
}
$redis->wait_all_responses;
#
# Read length of schedule, retry and dead queues
#
my $count_schedule = $redis->zcard("${key_prefix}schedule");
my $count_retry = $redis->zcard("${key_prefix}retry");
my $count_dead = $redis->zcard("${key_prefix}dead");
#
# Render queue graph
#
print "multigraph ${plugin_name}_queue\n";
print "queue.value $count_queue\n";
print "busy.value $count_busy\n";
print "schedule.value $count_schedule\n";
print "retry.value $count_retry\n";
print "dead.value $count_dead\n";
#
# Read processed and failed counter
#
my $count_processed = $redis->get("${key_prefix}stat:processed");
my $count_failed = $redis->get("${key_prefix}stat:failed");
#
# Render counter graph
#
print "multigraph ${plugin_name}_count\n";
print "processed.value $count_processed\n";
print "failed.value $count_failed\n";
exit 0;
# vim: ft=perl ai ts=4 sw=4 et:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment