|  |  | #!/usr/bin/env python
 | 
						
						
						
							|  |  | # -*- coding: utf-8 -*-
 | 
						
						
						
							|  |  | import os
 | 
						
						
						
							|  |  | import time
 | 
						
						
						
							|  |  | import optparse
 | 
						
						
						
							|  |  | from rq import use_redis, Queue, Worker
 | 
						
						
						
							|  |  | from rq.utils import gettermsize, make_colorizer
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | red = make_colorizer('darkred')
 | 
						
						
						
							|  |  | green = make_colorizer('darkgreen')
 | 
						
						
						
							|  |  | yellow = make_colorizer('darkyellow')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def pad(s, pad_to_length):
 | 
						
						
						
							|  |  |     """Pads the given string to the given length."""
 | 
						
						
						
							|  |  |     return ('%-' + '%ds' % pad_to_length) % (s,)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def get_scale(x):
 | 
						
						
						
							|  |  |     """Finds the lowest scale where x <= scale."""
 | 
						
						
						
							|  |  |     scales = [20, 50, 100, 200, 400, 600, 800, 1000]
 | 
						
						
						
							|  |  |     for scale in scales:
 | 
						
						
						
							|  |  |         if x <= scale:
 | 
						
						
						
							|  |  |             return scale
 | 
						
						
						
							|  |  |     return x
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def parse_args():
 | 
						
						
						
							|  |  |     parser = optparse.OptionParser()
 | 
						
						
						
							|  |  |     parser.add_option('-q', '--queues', dest='subcmd',
 | 
						
						
						
							|  |  |             action='store_const', const='queues',
 | 
						
						
						
							|  |  |             help='Shows stats for queues.')
 | 
						
						
						
							|  |  |     parser.add_option('-w', '--workers', dest='subcmd',
 | 
						
						
						
							|  |  |             action='store_const', const='workers',
 | 
						
						
						
							|  |  |             help='Shows stats for workers.')
 | 
						
						
						
							|  |  |     parser.add_option('-n', '--interval', dest='interval',
 | 
						
						
						
							|  |  |             type='float',
 | 
						
						
						
							|  |  |             help='The interval between polls, in seconds.  Does not poll if 0.')
 | 
						
						
						
							|  |  |     parser.add_option('-g', '--graph', dest='graph',
 | 
						
						
						
							|  |  |             action='store_true', default=False,
 | 
						
						
						
							|  |  |             help='Shows bar chart graphs where possible.')
 | 
						
						
						
							|  |  |     opts, args = parser.parse_args()
 | 
						
						
						
							|  |  |     return (opts, args, parser)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def show_queues(opts, args, parser):
 | 
						
						
						
							|  |  |     while True:
 | 
						
						
						
							|  |  |         if len(args):
 | 
						
						
						
							|  |  |             qs = map(Queue, args)
 | 
						
						
						
							|  |  |         else:
 | 
						
						
						
							|  |  |             qs = Queue.all()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         num_jobs = 0
 | 
						
						
						
							|  |  |         termwidth, _ = gettermsize()
 | 
						
						
						
							|  |  |         chartwidth = min(20, termwidth - 20)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         max_count = 0
 | 
						
						
						
							|  |  |         counts = dict()
 | 
						
						
						
							|  |  |         for q in qs:
 | 
						
						
						
							|  |  |             count = q.count
 | 
						
						
						
							|  |  |             counts[q] = count
 | 
						
						
						
							|  |  |             max_count = max(max_count, count)
 | 
						
						
						
							|  |  |         scale = get_scale(max_count)
 | 
						
						
						
							|  |  |         ratio = chartwidth * 1.0 / scale
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if opts.interval:
 | 
						
						
						
							|  |  |             os.system('clear')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         print('scale = %d' % scale)
 | 
						
						
						
							|  |  |         for q in qs:
 | 
						
						
						
							|  |  |             count = counts[q]
 | 
						
						
						
							|  |  |             if opts.graph:
 | 
						
						
						
							|  |  |                 chart = green('|' + '█' * int(ratio * count))
 | 
						
						
						
							|  |  |                 line = '%-12s %s %d' % (q.name, chart, count)
 | 
						
						
						
							|  |  |             else:
 | 
						
						
						
							|  |  |                 line = '%-12s %d' % (q.name, count)
 | 
						
						
						
							|  |  |             print(line)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |             num_jobs += count
 | 
						
						
						
							|  |  |         print('%d queues, %d jobs total' % (len(qs), num_jobs))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if opts.interval:
 | 
						
						
						
							|  |  |             time.sleep(opts.interval)
 | 
						
						
						
							|  |  |         else:
 | 
						
						
						
							|  |  |             break
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def state_symbol(state):
 | 
						
						
						
							|  |  |     symbols = {
 | 
						
						
						
							|  |  |         'busy': red(u'\u25CF'),
 | 
						
						
						
							|  |  |         'idle': green(u'\u25CB'),
 | 
						
						
						
							|  |  |     }
 | 
						
						
						
							|  |  |     try:
 | 
						
						
						
							|  |  |         return symbols[state]
 | 
						
						
						
							|  |  |     except KeyError:
 | 
						
						
						
							|  |  |         return state
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def show_workers(opts, args, parser):
 | 
						
						
						
							|  |  |     while True:
 | 
						
						
						
							|  |  |         qs = Queue.all()
 | 
						
						
						
							|  |  |         ws = Worker.all()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if opts.interval:
 | 
						
						
						
							|  |  |             os.system('clear')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         queues = {qname: [] for qname in qs}
 | 
						
						
						
							|  |  |         for w in ws:
 | 
						
						
						
							|  |  |             for q in w.queues:
 | 
						
						
						
							|  |  |                 if not q in queues:
 | 
						
						
						
							|  |  |                     queues[q] = []
 | 
						
						
						
							|  |  |                 queues[q].append(w)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         by_worker = False
 | 
						
						
						
							|  |  |         if by_worker:
 | 
						
						
						
							|  |  |             for w in ws:
 | 
						
						
						
							|  |  |                 print '%s %s: %s' % (w.name, state_symbol(w.state), ', '.join(w.queue_names()))
 | 
						
						
						
							|  |  |         else:
 | 
						
						
						
							|  |  |             max_qname = max(map(lambda q: len(q.name), queues.keys()))
 | 
						
						
						
							|  |  |             for q in queues:
 | 
						
						
						
							|  |  |                 if queues[q]:
 | 
						
						
						
							|  |  |                     queues_str = ", ".join(sorted(map(lambda w: '%s (%s)' % (w.name, state_symbol(w.state)), queues[q])))
 | 
						
						
						
							|  |  |                 else:
 | 
						
						
						
							|  |  |                     queues_str = '–'
 | 
						
						
						
							|  |  |                 print '%s %s' % (pad(q.name + ':', max_qname + 1), queues_str)
 | 
						
						
						
							|  |  |         print '%d workers, watching %d queues' % (len(ws), len(queues))
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |         if opts.interval:
 | 
						
						
						
							|  |  |             time.sleep(opts.interval)
 | 
						
						
						
							|  |  |         else:
 | 
						
						
						
							|  |  |             break
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | def main():
 | 
						
						
						
							|  |  |     opts, args, parser = parse_args()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     if not opts.subcmd:
 | 
						
						
						
							|  |  |         parser.error('Specify either --queues or --workers.')
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     use_redis()
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  |     if opts.subcmd == 'workers':
 | 
						
						
						
							|  |  |         show_workers(opts, args, parser)
 | 
						
						
						
							|  |  |     elif opts.subcmd == 'queues':
 | 
						
						
						
							|  |  |         show_queues(opts, args, parser)
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | 
 | 
						
						
						
							|  |  | if __name__ == '__main__':
 | 
						
						
						
							|  |  |     main()
 |