Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dumper.py 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.events.dumper
  4. ~~~~~~~~~~~~~~~~~~~~
  5. This is a simple program that dumps events to the console
  6. as they happen. Think of it like a `tcpdump` for Celery events.
  7. """
  8. from __future__ import absolute_import, print_function
  9. import sys
  10. from datetime import datetime
  11. from celery.app import app_or_default
  12. from celery.utils.functional import LRUCache
  13. from celery.utils.timeutils import humanize_seconds
  14. __all__ = ['Dumper', 'evdump']
  15. TASK_NAMES = LRUCache(limit=0xFFF)
  16. HUMAN_TYPES = {'worker-offline': 'shutdown',
  17. 'worker-online': 'started',
  18. 'worker-heartbeat': 'heartbeat'}
  19. CONNECTION_ERROR = """\
  20. -> Cannot connect to %s: %s.
  21. Trying again %s
  22. """
  23. def humanize_type(type):
  24. try:
  25. return HUMAN_TYPES[type.lower()]
  26. except KeyError:
  27. return type.lower().replace('-', ' ')
  28. class Dumper(object):
  29. def __init__(self, out=sys.stdout):
  30. self.out = out
  31. def say(self, msg):
  32. print(msg, file=self.out)
  33. # need to flush so that output can be piped.
  34. try:
  35. self.out.flush()
  36. except AttributeError:
  37. pass
  38. def on_event(self, ev):
  39. timestamp = datetime.utcfromtimestamp(ev.pop('timestamp'))
  40. type = ev.pop('type').lower()
  41. hostname = ev.pop('hostname')
  42. if type.startswith('task-'):
  43. uuid = ev.pop('uuid')
  44. if type in ('task-received', 'task-sent'):
  45. task = TASK_NAMES[uuid] = '{0}({1}) args={2} kwargs={3}' \
  46. .format(ev.pop('name'), uuid,
  47. ev.pop('args'),
  48. ev.pop('kwargs'))
  49. else:
  50. task = TASK_NAMES.get(uuid, '')
  51. return self.format_task_event(hostname, timestamp,
  52. type, task, ev)
  53. fields = ', '.join(
  54. '{0}={1}'.format(key, ev[key]) for key in sorted(ev)
  55. )
  56. sep = fields and ':' or ''
  57. self.say('{0} [{1}] {2}{3} {4}'.format(
  58. hostname, timestamp, humanize_type(type), sep, fields),
  59. )
  60. def format_task_event(self, hostname, timestamp, type, task, event):
  61. fields = ', '.join(
  62. '{0}={1}'.format(key, event[key]) for key in sorted(event)
  63. )
  64. sep = fields and ':' or ''
  65. self.say('{0} [{1}] {2}{3} {4} {5}'.format(
  66. hostname, timestamp, humanize_type(type), sep, task, fields),
  67. )
  68. def evdump(app=None, out=sys.stdout):
  69. app = app_or_default(app)
  70. dumper = Dumper(out=out)
  71. dumper.say('-> evdump: starting capture...')
  72. conn = app.connection().clone()
  73. def _error_handler(exc, interval):
  74. dumper.say(CONNECTION_ERROR % (
  75. conn.as_uri(), exc, humanize_seconds(interval, 'in', ' ')
  76. ))
  77. while 1:
  78. try:
  79. conn.ensure_connection(_error_handler)
  80. recv = app.events.Receiver(conn, handlers={'*': dumper.on_event})
  81. recv.capture()
  82. except (KeyboardInterrupt, SystemExit):
  83. return conn and conn.close()
  84. except conn.connection_errors + conn.channel_errors:
  85. dumper.say('-> Connection lost, attempting reconnect')
  86. if __name__ == '__main__': # pragma: no cover
  87. evdump()