monitoring.rst 19 KB

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