monitoring.rst 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. .. _guide-monitoring:
  2. =================================
  3. Monitoring and Management Guide
  4. =================================
  5. .. contents::
  6. :local:
  7. Introduction
  8. ============
  9. There are several tools available to monitor and inspect Celery clusters.
  10. This document describes some of these, as as well as
  11. features related to monitoring, like events and broadcast commands.
  12. .. _monitoring-workers:
  13. Workers
  14. =======
  15. .. _monitoring-celeryctl:
  16. ``celery``: Management Command-line Utilities
  17. ---------------------------------------------
  18. .. versionadded:: 2.1
  19. :program:`celery` can also be used to inspect
  20. and manage worker nodes (and to some degree tasks).
  21. To list all the commands available do:
  22. .. code-block:: bash
  23. $ celery help
  24. or to get help for a specific command do:
  25. .. code-block:: bash
  26. $ celery <command> --help
  27. Commands
  28. ~~~~~~~~
  29. * **shell**: Drop into a Python shell.
  30. The locals will include the ``celery`` variable, which is the current app.
  31. Also all known tasks will be automatically added to locals (unless the
  32. ``--without-tasks`` flag is set).
  33. Uses Ipython, bpython, or regular python in that order if installed.
  34. You can force an implementation using ``--force-ipython|-I``,
  35. ``--force-bpython|-B``, or ``--force-python|-P``.
  36. * **status**: List active nodes in this cluster
  37. .. code-block:: bash
  38. $ celery status
  39. * **result**: Show the result of a task
  40. .. code-block:: bash
  41. $ celery result -t tasks.add 4e196aa4-0141-4601-8138-7aa33db0f577
  42. Note that you can omit the name of the task as long as the
  43. task doesn't use a custom result backend.
  44. * **purge**: Purge messages from all configured task queues.
  45. .. code-block:: bash
  46. $ celery purge
  47. .. warning::
  48. There is no undo for this operation, and messages will
  49. be permanently deleted!
  50. * **inspect active**: List active tasks
  51. .. code-block:: bash
  52. $ celery inspect active
  53. These are all the tasks that are currently being executed.
  54. * **inspect scheduled**: List scheduled ETA tasks
  55. .. code-block:: bash
  56. $ celery inspect scheduled
  57. These are tasks reserved by the worker because they have the
  58. `eta` or `countdown` argument set.
  59. * **inspect reserved**: List reserved tasks
  60. .. code-block:: bash
  61. $ celery inspect reserved
  62. This will list all tasks that have been prefetched by the worker,
  63. and is currently waiting to be executed (does not include tasks
  64. with an eta).
  65. * **inspect revoked**: List history of revoked tasks
  66. .. code-block:: bash
  67. $ celery inspect revoked
  68. * **inspect registered**: List registered tasks
  69. .. code-block:: bash
  70. $ celery inspect registered
  71. * **inspect stats**: Show worker statistics
  72. .. code-block:: bash
  73. $ celery inspect stats
  74. * **control enable_events**: Enable events
  75. .. code-block:: bash
  76. $ celery control enable_events
  77. * **control disable_events**: Disable events
  78. .. code-block:: bash
  79. $ celery inspect disable_events
  80. * **migrate**: Migrate tasks from one broker to another (**EXPERIMENTAL**).
  81. .. code-block:: bash
  82. $ celery migrate redis://localhost amqp://localhost
  83. This command will migrate all the tasks on one broker to another.
  84. As this command is new and experimental you should be sure to have
  85. a backup of the data before proceeding.
  86. .. note::
  87. All ``inspect`` commands supports a ``--timeout`` argument,
  88. This is the number of seconds to wait for responses.
  89. You may have to increase this timeout if you're not getting a response
  90. due to latency.
  91. .. _celeryctl-inspect-destination:
  92. Specifying destination nodes
  93. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  94. By default the inspect commands operates on all workers.
  95. You can specify a single, or a list of workers by using the
  96. `--destination` argument:
  97. .. code-block:: bash
  98. $ celery inspect -d w1,w2 reserved
  99. .. _monitoring-flower:
  100. Flower: Real-time Celery web-monitor
  101. ------------------------------------
  102. Flower is a real-time web based monitor and administration tool for Celery.
  103. It is under active development, but is already an essential tool.
  104. Being the recommended monitor for Celery, it obsoletes the Django-Admin
  105. monitor, celerymon and the ncurses based monitor.
  106. Flower is pronounced like "flow", but you can also use the botanical version
  107. if you prefer.
  108. Features
  109. ~~~~~~~~
  110. - Real-time monitoring using Celery Events
  111. - Task progress and history.
  112. - Ability to show task details (arguments, start time, runtime, and more)
  113. - Graphs and statistics
  114. - Remote Control
  115. - View worker status and statistics.
  116. - Shutdown and restart worker instances.
  117. - Control worker pool size and autoscale settings.
  118. - View and modify the queues a worker instance consumes from.
  119. - View currently running tasks
  120. - View scheduled tasks (ETA/countdown)
  121. - View reserved and revoked tasks
  122. - Apply time and rate limits
  123. - Configuration viewer
  124. - Revoke or terminate tasks
  125. - HTTP API
  126. - OpenID authentication
  127. **Screenshots**
  128. .. figure:: ../images/dashboard.png
  129. :width: 700px
  130. .. figure:: ../images/monitor.png
  131. :width: 700px
  132. More screenshots_:
  133. .. _screenshots: https://github.com/mher/flower/tree/master/docs/screenshots
  134. Usage
  135. ~~~~~
  136. You can use pip to install Flower:
  137. .. code-block:: bash
  138. $ pip install flower
  139. Running the flower command will start a web-server that you can visit:
  140. .. code-block:: bash
  141. $ celery flower
  142. The default port is http://localhost:5555, but you can change this using the
  143. :option:`--port` argument::
  144. $ open http://localhost:5555
  145. .. _monitoring-celeryev:
  146. celery events: Curses Monitor
  147. -----------------------------
  148. .. versionadded:: 2.0
  149. `celery events` is a simple curses monitor displaying
  150. task and worker history. You can inspect the result and traceback of tasks,
  151. and it also supports some management commands like rate limiting and shutting
  152. down workers. This monitor was started as a proof of concept, and you
  153. probably want to use Flower instead.
  154. Starting:
  155. .. code-block:: bash
  156. $ celery events
  157. You should see a screen like:
  158. .. figure:: ../images/celeryevshotsm.jpg
  159. `celery events` is also used to start snapshot cameras (see
  160. :ref:`monitoring-snapshots`:
  161. .. code-block:: bash
  162. $ celery events --camera=<camera-class> --frequency=1.0
  163. and it includes a tool to dump events to :file:`stdout`:
  164. .. code-block:: bash
  165. $ celery events --dump
  166. For a complete list of options use ``--help``:
  167. .. code-block:: bash
  168. $ celery events --help
  169. .. _`celerymon`: http://github.com/celery/celerymon/
  170. .. _monitoring-rabbitmq:
  171. RabbitMQ
  172. ========
  173. To manage a Celery cluster it is important to know how
  174. RabbitMQ can be monitored.
  175. RabbitMQ ships with the `rabbitmqctl(1)`_ command,
  176. with this you can list queues, exchanges, bindings,
  177. queue lengths, the memory usage of each queue, as well
  178. as manage users, virtual hosts and their permissions.
  179. .. note::
  180. The default virtual host (``"/"``) is used in these
  181. examples, if you use a custom virtual host you have to add
  182. the ``-p`` argument to the command, e.g:
  183. ``rabbitmqctl list_queues -p my_vhost ....``
  184. .. _`rabbitmqctl(1)`: http://www.rabbitmq.com/man/rabbitmqctl.1.man.html
  185. .. _monitoring-rmq-queues:
  186. Inspecting queues
  187. -----------------
  188. Finding the number of tasks in a queue:
  189. .. code-block:: bash
  190. $ rabbitmqctl list_queues name messages messages_ready \
  191. messages_unacknowledged
  192. Here `messages_ready` is the number of messages ready
  193. for delivery (sent but not received), `messages_unacknowledged`
  194. is the number of messages that has been received by a worker but
  195. not acknowledged yet (meaning it is in progress, or has been reserved).
  196. `messages` is the sum of ready and unacknowledged messages.
  197. Finding the number of workers currently consuming from a queue:
  198. .. code-block:: bash
  199. $ rabbitmqctl list_queues name consumers
  200. Finding the amount of memory allocated to a queue:
  201. .. code-block:: bash
  202. $ rabbitmqctl list_queues name memory
  203. :Tip: Adding the ``-q`` option to `rabbitmqctl(1)`_ makes the output
  204. easier to parse.
  205. .. _monitoring-redis:
  206. Redis
  207. =====
  208. If you're using Redis as the broker, you can monitor the Celery cluster using
  209. the `redis-cli(1)` command to list lengths of queues.
  210. .. _monitoring-redis-queues:
  211. Inspecting queues
  212. -----------------
  213. Finding the number of tasks in a queue:
  214. .. code-block:: bash
  215. $ redis-cli -h HOST -p PORT -n DATABASE_NUMBER llen QUEUE_NAME
  216. The default queue is named `celery`. To get all available queues, invoke:
  217. .. code-block:: bash
  218. $ redis-cli -h HOST -p PORT -n DATABASE_NUMBER keys \*
  219. .. note::
  220. If a list has no elements in Redis, it doesn't exist. Hence it won't show up
  221. in the `keys` command output. `llen` for that list returns 0 in that case.
  222. On the other hand, if you're also using Redis for other purposes, the output
  223. of the `keys` command will include unrelated values stored in the database.
  224. The recommended way around this is to use a dedicated `DATABASE_NUMBER` for
  225. Celery.
  226. .. _monitoring-munin:
  227. Munin
  228. =====
  229. This is a list of known Munin plug-ins that can be useful when
  230. maintaining a Celery cluster.
  231. * rabbitmq-munin: Munin plug-ins for RabbitMQ.
  232. http://github.com/ask/rabbitmq-munin
  233. * celery_tasks: Monitors the number of times each task type has
  234. been executed (requires `celerymon`).
  235. http://exchange.munin-monitoring.org/plugins/celery_tasks-2/details
  236. * celery_task_states: Monitors the number of tasks in each state
  237. (requires `celerymon`).
  238. http://exchange.munin-monitoring.org/plugins/celery_tasks/details
  239. .. _monitoring-events:
  240. Events
  241. ======
  242. The worker has the ability to send a message whenever some event
  243. happens. These events are then captured by tools like Flower,
  244. and :program:`celery events` to monitor the cluster.
  245. .. _monitoring-snapshots:
  246. Snapshots
  247. ---------
  248. .. versionadded:: 2.1
  249. Even a single worker can produce a huge amount of events, so storing
  250. the history of all events on disk may be very expensive.
  251. A sequence of events describes the cluster state in that time period,
  252. by taking periodic snapshots of this state you can keep all history, but
  253. still only periodically write it to disk.
  254. To take snapshots you need a Camera class, with this you can define
  255. what should happen every time the state is captured; You can
  256. write it to a database, send it by email or something else entirely.
  257. :program:`celery events` is then used to take snapshots with the camera,
  258. for example if you want to capture state every 2 seconds using the
  259. camera ``myapp.Camera`` you run :program:`celery events` with the following
  260. arguments:
  261. .. code-block:: bash
  262. $ celery events -c myapp.Camera --frequency=2.0
  263. .. _monitoring-camera:
  264. Custom Camera
  265. ~~~~~~~~~~~~~
  266. Cameras can be useful if you need to capture events and do something
  267. with those events at an interval. For real-time event processing
  268. you should use :class:`@events.Receiver` directly, like in
  269. :ref:`event-real-time-example`.
  270. Here is an example camera, dumping the snapshot to screen:
  271. .. code-block:: python
  272. from pprint import pformat
  273. from celery.events.snapshot import Polaroid
  274. class DumpCam(Polaroid):
  275. def on_shutter(self, state):
  276. if not state.event_count:
  277. # No new events since last snapshot.
  278. return
  279. print('Workers: {0}'.format(pformat(state.workers, indent=4)))
  280. print('Tasks: {0}'.format(pformat(state.tasks, indent=4)))
  281. print('Total: {0.event_count} events, %s {0.task_count}'.format(
  282. state))
  283. See the API reference for :mod:`celery.events.state` to read more
  284. about state objects.
  285. Now you can use this cam with :program:`celery events` by specifying
  286. it with the :option:`-c` option:
  287. .. code-block:: bash
  288. $ celery events -c myapp.DumpCam --frequency=2.0
  289. Or you can use it programmatically like this:
  290. .. code-block:: python
  291. from celery import Celery
  292. from myapp import DumpCam
  293. def main(app, freq=1.0):
  294. state = app.events.State()
  295. with app.connection() as connection:
  296. recv = app.events.Receiver(connection, handlers={'*': state.event})
  297. with DumpCam(state, freq=freq):
  298. recv.capture(limit=None, timeout=None)
  299. if __name__ == '__main__':
  300. celery = Celery(broker='amqp://guest@localhost//')
  301. main(celery)
  302. .. _event-real-time-example:
  303. Real-time processing
  304. --------------------
  305. To process events in real-time you need the following
  306. - An event consumer (this is the ``Receiver``)
  307. - A set of handlers called when events come in.
  308. You can have different handlers for each event type,
  309. or a catch-all handler can be used ('*')
  310. - State (optional)
  311. :class:`@events.State` is a convenient in-memory representation
  312. of tasks and workers in the cluster that is updated as events come in.
  313. It encapsulates solutions for many common things, like checking if a
  314. worker is still alive (by verifying heartbeats), merging event fields
  315. together as events come in, making sure timestamps are in sync, and so on.
  316. Combining these you can easily process events in real-time:
  317. .. code-block:: python
  318. from celery import Celery
  319. def monitor_events(app):
  320. state = app.events.State()
  321. def on_event(event):
  322. state.event(event) # <-- updates in-memory cluster state
  323. print('Workers online: %r' % ', '.join(
  324. worker for worker in state.workers if worker.alive
  325. )
  326. with app.connection() as connection:
  327. recv = app.events.Receiver(connection, handlers={'*': on_event})
  328. recv.capture(limit=None, timeout=None, wakeup=True)
  329. .. note::
  330. The wakeup argument to ``capture`` sends a signal to all workers
  331. to force them to send a heartbeat. This way you can immediately see
  332. workers when the monitor starts.
  333. You can listen to specific events by specifying the handlers:
  334. .. code-block:: python
  335. from celery import Celery
  336. def my_monitor(app):
  337. state = app.events.State()
  338. def announce_failed_tasks(event):
  339. state.event(event)
  340. task_id = event['uuid']
  341. print('TASK FAILED: %s[%s] %s' % (
  342. event['name'], task_id, state[task_id].info(), ))
  343. def announce_dead_workers(event):
  344. state.event(event)
  345. hostname = event['hostname']
  346. if not state.workers[hostname].alive:
  347. print('Worker %s missed heartbeats' % (hostname, ))
  348. with app.connection() as connection:
  349. recv = app.events.Receiver(connection, handlers={
  350. 'task-failed': announce_failed_tasks,
  351. 'worker-heartbeat': announce_dead_workers,
  352. })
  353. recv.capture(limit=None, timeout=None, wakeup=True)
  354. if __name__ == '__main__':
  355. celery = Celery(broker='amqp://guest@localhost//')
  356. my_monitor(celery)
  357. .. _event-reference:
  358. Event Reference
  359. ===============
  360. This list contains the events sent by the worker, and their arguments.
  361. .. _event-reference-task:
  362. Task Events
  363. -----------
  364. .. event:: task-sent
  365. task-sent
  366. ~~~~~~~~~
  367. :signature: ``task-sent(uuid, name, args, kwargs, retries, eta, expires,
  368. queue, exchange, routing_key)``
  369. Sent when a task message is published and
  370. the :setting:`CELERY_SEND_TASK_SENT_EVENT` setting is enabled.
  371. .. event:: task-received
  372. task-received
  373. ~~~~~~~~~~~~~
  374. :signature: ``task-received(uuid, name, args, kwargs, retries, eta, hostname,
  375. timestamp)``
  376. Sent when the worker receives a task.
  377. .. event:: task-started
  378. task-started
  379. ~~~~~~~~~~~~
  380. :signature: ``task-started(uuid, hostname, timestamp, pid)``
  381. Sent just before the worker executes the task.
  382. .. event:: task-succeeded
  383. task-succeeded
  384. ~~~~~~~~~~~~~~
  385. :signature: ``task-succeeded(uuid, result, runtime, hostname, timestamp)``
  386. Sent if the task executed successfully.
  387. Runtime is the time it took to execute the task using the pool.
  388. (Starting from the task is sent to the worker pool, and ending when the
  389. pool result handler callback is called).
  390. .. event:: task-failed
  391. task-failed
  392. ~~~~~~~~~~~
  393. :signature: ``task-failed(uuid, exception, traceback, hostname, timestamp)``
  394. Sent if the execution of the task failed.
  395. .. event:: task-revoked
  396. task-revoked
  397. ~~~~~~~~~~~~
  398. :signature: ``task-revoked(uuid, terminated, signum, expired)``
  399. Sent if the task has been revoked (Note that this is likely
  400. to be sent by more than one worker).
  401. - ``terminated`` is set to true if the task process was terminated,
  402. and the ``signum`` field set to the signal used.
  403. - ``expired`` is set to true if the task expired.
  404. .. event:: task-retried
  405. task-retried
  406. ~~~~~~~~~~~~
  407. :signature: ``task-retried(uuid, exception, traceback, hostname, timestamp)``
  408. Sent if the task failed, but will be retried in the future.
  409. .. _event-reference-worker:
  410. Worker Events
  411. -------------
  412. .. event:: worker-online
  413. worker-online
  414. ~~~~~~~~~~~~~
  415. :signature: ``worker-online(hostname, timestamp, freq, sw_ident, sw_ver, sw_sys)``
  416. The worker has connected to the broker and is online.
  417. - `hostname`: Hostname of the worker.
  418. - `timestamp`: Event timestamp.
  419. - `freq`: Heartbeat frequency in seconds (float).
  420. - `sw_ident`: Name of worker software (e.g. ``py-celery``).
  421. - `sw_ver`: Software version (e.g. 2.2.0).
  422. - `sw_sys`: Operating System (e.g. Linux, Windows, Darwin).
  423. .. event:: worker-heartbeat
  424. worker-heartbeat
  425. ~~~~~~~~~~~~~~~~
  426. :signature: ``worker-heartbeat(hostname, timestamp, freq, sw_ident, sw_ver, sw_sys,
  427. active, processed)``
  428. Sent every minute, if the worker has not sent a heartbeat in 2 minutes,
  429. it is considered to be offline.
  430. - `hostname`: Hostname of the worker.
  431. - `timestamp`: Event timestamp.
  432. - `freq`: Heartbeat frequency in seconds (float).
  433. - `sw_ident`: Name of worker software (e.g. ``py-celery``).
  434. - `sw_ver`: Software version (e.g. 2.2.0).
  435. - `sw_sys`: Operating System (e.g. Linux, Windows, Darwin).
  436. - `active`: Number of currently executing tasks.
  437. - `processed`: Total number of tasks processed by this worker.
  438. .. event:: worker-offline
  439. worker-offline
  440. ~~~~~~~~~~~~~~
  441. :signature: ``worker-offline(hostname, timestamp, freq, sw_ident, sw_ver, sw_sys)``
  442. The worker has disconnected from the broker.