├── .gitignore ├── AUTHORS ├── Changelog ├── LICENSE ├── MANIFEST.in ├── README ├── README.rst ├── TODO ├── celerymon ├── __init__.py ├── bin │ ├── __init__.py │ └── celerymon.py ├── consumer.py ├── handlers │ ├── __init__.py │ ├── api.py │ └── main.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── celerymon.py ├── service.py ├── state.py ├── static │ ├── analytics.tsv │ ├── css │ │ └── master.css │ ├── favicon.ico │ ├── highcharts │ │ ├── examples │ │ │ ├── analytics.tsv │ │ │ ├── area-basic.htm │ │ │ ├── area-inverted.htm │ │ │ ├── area-missing.htm │ │ │ ├── area-negative.htm │ │ │ ├── area-stacked-percent.htm │ │ │ ├── area-stacked.htm │ │ │ ├── areaspline.htm │ │ │ ├── bar-basic.htm │ │ │ ├── bar-negative-stack.htm │ │ │ ├── bar-stacked.htm │ │ │ ├── column-basic.htm │ │ │ ├── column-drilldown.htm │ │ │ ├── column-negative.htm │ │ │ ├── column-parsed.htm │ │ │ ├── column-rotated-labels.htm │ │ │ ├── column-stacked-and-grouped.htm │ │ │ ├── column-stacked-percent.htm │ │ │ ├── column-stacked.htm │ │ │ ├── combo-dual-axes.htm │ │ │ ├── combo-multi-axes.htm │ │ │ ├── combo-regression.htm │ │ │ ├── combo.htm │ │ │ ├── dynamic-click-to-add.htm │ │ │ ├── dynamic-master-detail.htm │ │ │ ├── dynamic-update.htm │ │ │ ├── line-ajax.htm │ │ │ ├── line-basic.htm │ │ │ ├── line-labels.htm │ │ │ ├── line-time-series.htm │ │ │ ├── pie-basic.htm │ │ │ ├── pie-donut.htm │ │ │ ├── pie-legend.htm │ │ │ ├── scatter.htm │ │ │ ├── spline-inverted.htm │ │ │ ├── spline-irregular-time.htm │ │ │ ├── spline-plot-bands.htm │ │ │ └── spline-symbols.htm │ │ ├── exporting-server │ │ │ └── index.php │ │ ├── graphics │ │ │ ├── skies.jpg │ │ │ ├── snow.png │ │ │ └── sun.png │ │ ├── index.htm │ │ └── js │ │ │ ├── adapters │ │ │ ├── mootools-adapter.js │ │ │ ├── mootools-adapter.src.js │ │ │ ├── prototype-adapter.js │ │ │ └── prototype-adapter.src.js │ │ │ ├── highcharts.js │ │ │ ├── highcharts.src.js │ │ │ ├── modules │ │ │ ├── exporting.js │ │ │ └── exporting.src.js │ │ │ └── themes │ │ │ ├── dark-blue.js │ │ │ ├── dark-green.js │ │ │ ├── gray.js │ │ │ └── grid.js │ └── images │ │ └── logo.png ├── templates │ ├── api_detail.html │ ├── index.html │ └── template.html └── web.py ├── requirements └── default.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | *~ 4 | .*.sw[po] 5 | dist/ 6 | *.egg-info 7 | doc/__build/* 8 | build/ 9 | .build/ 10 | pip-log.txt 11 | .directory 12 | celeryconfig.py 13 | test.py 14 | 15 | # IDE 16 | *.iml 17 | .idea/ -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Ordered by date of first contribution: 2 | Ask Solem 3 | Tomaž Muraus 4 | Jonas Haag 5 | Paul McLanahan 6 | Juan Catalano 7 | Paul Trippett 8 | Atsuo Ishimoto 9 | Alexander A. Sosnovskiy 10 | Tomasz Wójcik 11 | Roman Sęk 12 | Blake Eggleston 13 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | ============== 2 | Change history 3 | ============== 4 | 5 | 1.0.3 6 | ===== 7 | 8 | * Code cleanup. 9 | 10 | 1.0.2 11 | ===== 12 | 13 | * :program:`celery mon` now the respects :option:`--pidfile` option 14 | (Issue #14). 15 | 16 | Fix contributed by Atsuo Ishimoto. 17 | 18 | 1.0.1 19 | ===== 20 | 21 | * Distribution did not include static files (Issue #17). 22 | 23 | 1.0.0 24 | ===== 25 | 26 | * Adds a UI to the frontpage 27 | 28 | Contributed by Paul Trippett. 29 | 30 | 0.5.0 31 | ===== 32 | 33 | * Now supports Celery 3.x 34 | 35 | 0.4.0 36 | ===== 37 | 38 | * No longer supports Python 2.4 39 | 40 | * Requires Celery >= 2.3 41 | 42 | * Package renamed from ``celerymonitor`` -> ``celerymon``. 43 | 44 | The long name was used because of relative imports clashes, 45 | but this is no longer an issue since we have dropped 46 | Python 2.4 support and can force absolute imports. 47 | 48 | * celerymon can now be daemonized using the `--detach` option. 49 | 50 | Additional daemon related options are available, see ``celerymon --help`` 51 | for a list of these. 52 | 53 | Contributed by Juan Catalano. 54 | 55 | 0.3.0 56 | ===== 57 | 58 | * Updated to work with Celery v2.2.x. 59 | 60 | 0.2.2 61 | ===== 62 | 63 | * Updated to work with Celery v2.1.0. 64 | 65 | 0.1.0 [xxxx-xx-xx xx:xx x.x xxx] 66 | ================================ 67 | 68 | * Initial release. 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Ask Solem 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of Ask Solem nor the names of its contributors may be used 14 | to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS 2 | include Changelog 3 | include README.rst 4 | include MANIFEST.in 5 | include LICENSE 6 | include TODO 7 | recursive-include celerymon *.py 8 | recursive-include celerymon/templates *.html 9 | recursive-include celerymon/static * 10 | prune celerymon/*.pyc 11 | prune bin/*.pyc 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ==================================================== 2 | celerymon - Real-time monitoring of Celery workers 3 | ==================================================== 4 | 5 | Celery 4+ monitoring app based on asgi & python 3.6+ 6 | ======================================================================= 7 | 8 | 9 | 10 | :Version: 0.0.1 11 | 12 | Installation 13 | ============= 14 | 15 | You can install ``celerymon`` either via the Python Package Index (PyPI) 16 | or from source. 17 | 18 | To install using ``pip``,:: 19 | 20 | $ pip3 install celerymon 21 | 22 | 23 | Downloading and installing from source 24 | -------------------------------------- 25 | 26 | Download the latest version of ``celerymon`` from 27 | http://pypi.python.org/pypi/celerymon/ 28 | 29 | You can install it by doing the following,:: 30 | 31 | $ tar xvfz celerymon-0.0.0.tar.gz 32 | $ cd celerymon-0.0.0 33 | $ python setup.py build 34 | # python setup.py install # as root 35 | 36 | Using the development version 37 | ------------------------------ 38 | 39 | You can clone the repository by doing the following:: 40 | 41 | $ git clone git://github.com/celery/celerymon.git 42 | 43 | 44 | Usage 45 | ===== 46 | 47 | Running the monitor 48 | ------------------- 49 | 50 | Start celery with the ``--events`` option on, so celery sends events for 51 | celerymon to capture:: 52 | 53 | $ python manage.py celeryd -E 54 | 55 | Run the monitor server:: 56 | 57 | $ python manage.py celerymon 58 | 59 | 60 | However, in production you probably want to run the monitor in the 61 | background, as a daemon:: 62 | 63 | $ python manage.py celerymon --detach 64 | 65 | 66 | For a complete listing of the command line arguments available, with a short 67 | description, you can use the help command:: 68 | 69 | $ python manage.py help celerymon 70 | 71 | 72 | Now you can visit the webserver celerymon starts by going to: 73 | http://localhost:8989 74 | 75 | 76 | Mailing list 77 | ------------ 78 | 79 | For discussions about the usage, development, and future of celery, 80 | please join the `celery-users`_ mailing list. 81 | 82 | .. _`celery-users`: http://groups.google.com/group/celery-users/ 83 | 84 | IRC 85 | --- 86 | 87 | Come chat with us on IRC. The **#celery** channel is located at the `Freenode`_ 88 | network. 89 | 90 | .. _`Freenode`: http://freenode.net 91 | 92 | 93 | Bug tracker 94 | =========== 95 | 96 | If you have any suggestions, bug reports or annoyances please report them 97 | to our issue tracker at http://github.com/celery/celerymon/issues/ 98 | 99 | Contributing 100 | ============ 101 | 102 | Development of ``celerymon`` happens at Github: 103 | http://github.com/celery/celerymon 104 | 105 | You are highly encouraged to participate in the development 106 | of ``celerymon``. If you don't like Github (for some reason) you're welcome 107 | to send regular patches. 108 | 109 | License 110 | ======= 111 | 112 | This software is licensed under the ``New BSD License``. See the ``LICENSE`` 113 | file in the top distribution directory for the full license text. 114 | 115 | .. # vim: syntax=rst expandtab tabstop=4 shiftwidth=4 shiftround 116 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Please see our Issue Tracker at GitHub: 2 | http://github.com/celery/celerymon/issues 3 | -------------------------------------------------------------------------------- /celerymon/__init__.py: -------------------------------------------------------------------------------- 1 | """Real-time monitoring of Celery workers.""" 2 | 3 | VERSION = (2, 0, 0) 4 | 5 | __version__ = '.'.join(map(str, VERSION)) 6 | __author__ = 'Asif Saif Uddin' 7 | __contact__ = 'auvipy@gmail.com' 8 | __homepage__ = 'http://github.com/auvipy/celerymon/' 9 | __docformat__ = 'restructuredtext' 10 | -------------------------------------------------------------------------------- /celerymon/bin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/bin/__init__.py -------------------------------------------------------------------------------- /celerymon/bin/celerymon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """celerymon 3 | 4 | .. program:: celerymon 5 | 6 | .. cmdoption:: -P, --port 7 | 8 | Port the webserver should listen to. Default: ``8989``. 9 | 10 | .. cmdoption:: -B, --bind 11 | 12 | Address the webserver should bind to. Default (any). 13 | 14 | .. cmdoption:: -f, --logfile 15 | 16 | Path to log file. If no logfile is specified, ``stderr`` is used. 17 | 18 | .. cmdoption:: -l, --loglevel 19 | 20 | .. cmdoption:: -D, --detach 21 | 22 | Daemonize celerymon. 23 | 24 | Logging level, choose between ``DEBUG``, ``INFO``, ``WARNING``, 25 | ``ERROR``, ``CRITICAL``, or ``FATAL``. 26 | 27 | """ 28 | 29 | import os 30 | import sys 31 | 32 | from celery.bin.base import Command, Option, daemon_options 33 | from celery.platforms import ( 34 | detached, 35 | set_process_title, 36 | strargv, 37 | create_pidlock, 38 | ) 39 | from celery.utils import LOG_LEVELS 40 | 41 | from .. import __version__ 42 | from ..service import MonitorService 43 | 44 | STARTUP_INFO_FMT = """ 45 | Configuration -> 46 | . broker -> %(conninfo)s 47 | . webserver -> http://%(http_address)s:%(http_port)s 48 | """.strip() 49 | 50 | OPTION_LIST = ( 51 | ) 52 | 53 | PID_FILE = 'celerymon.pid' 54 | 55 | 56 | class MonitorCommand(Command): 57 | namespace = 'celerymon' 58 | enable_config_from_cmdline = True 59 | version = __version__ 60 | 61 | def run(self, loglevel='ERROR', logfile=None, http_port=8989, 62 | http_address='', app=None, detach=False, pidfile=PID_FILE, 63 | uid=None, gid=None, umask=None, working_directory=None, **kwargs): 64 | print('celerymon %s is starting.' % self.version) 65 | app = self.app 66 | workdir = working_directory 67 | 68 | # Setup logging 69 | if not isinstance(loglevel, int): 70 | loglevel = LOG_LEVELS[loglevel.upper()] 71 | 72 | # Dump configuration to screen so we have some basic information 73 | # when users sends e-mails. 74 | print(STARTUP_INFO_FMT % { 75 | 'http_port': http_port, 76 | 'http_address': http_address or 'localhost', 77 | 'conninfo': app.broker_connection().as_uri(), 78 | }) 79 | 80 | print('celerymon has started.') 81 | set_process_title('celerymon', info=strargv(sys.argv)) 82 | 83 | def _run_monitor(): 84 | create_pidlock(pidfile) 85 | app.log.setup_logging_subsystem(loglevel=loglevel, 86 | logfile=logfile) 87 | logger = app.log.get_default_logger(name='celery.mon') 88 | monitor = MonitorService(logger=logger, 89 | http_port=http_port, 90 | http_address=http_address) 91 | 92 | try: 93 | monitor.start() 94 | except Exception, exc: 95 | logger.error('celerymon raised exception %r', 96 | exc, exc_info=True) 97 | except KeyboardInterrupt: 98 | pass 99 | 100 | if detach: 101 | with detached(logfile, pidfile, uid, gid, umask, workdir): 102 | _run_monitor() 103 | else: 104 | _run_monitor() 105 | 106 | def prepare_preload_options(self, options): 107 | workdir = options.get('working_directory') 108 | if workdir: 109 | os.chdir(workdir) 110 | 111 | def get_options(self): 112 | conf = self.app.conf 113 | return ( 114 | ( 115 | Option('-l', '--loglevel', 116 | default=conf.CELERYMON_LOG_LEVEL, 117 | help='Choose between DEBUG/INFO/WARNING/ERROR/CRITICAL.'), 118 | Option('-P', '--port', 119 | type='int', dest='http_port', default=8989, 120 | help='Port the webserver should listen to.'), 121 | Option('-B', '--bind', 122 | dest='http_address', default='', 123 | help='Address webserver should listen to. Default (any).'), 124 | Option('-D', '--detach', 125 | action='store_true', help='Run as daemon.') 126 | ) + daemon_options('celerymon.pid') 127 | ) 128 | 129 | 130 | # celery 3.x extension command 131 | try: 132 | from celery.bin.celery import Delegate 133 | 134 | class MonitorDelegate(Delegate): 135 | Command = MonitorCommand 136 | except ImportError: 137 | # celery 3.1 138 | try: 139 | MonitorDelegate = MonitorCommand 140 | except ImportError: # pre extension support 141 | class MonitorDelegate(object): # noqa 142 | pass 143 | 144 | 145 | def main(): 146 | mon = MonitorCommand() 147 | mon.execute_from_commandline() 148 | 149 | 150 | if __name__ == '__main__': 151 | main() 152 | -------------------------------------------------------------------------------- /celerymon/consumer.py: -------------------------------------------------------------------------------- 1 | from celery import current_app 2 | from celerymon.state import state 3 | 4 | 5 | class EventConsumer: 6 | """Capture events sent by messages and store them in memory.""" 7 | 8 | def __init__(self, state=state): 9 | self.app = current_app 10 | self.state = state 11 | self.connection = self.app.broker_connection() 12 | self.receiver = self.app.events.Receiver( 13 | self.connection, 14 | handlers={'*': self.state.event} 15 | ) 16 | 17 | def start(self): 18 | self.receiver.capture() 19 | -------------------------------------------------------------------------------- /celerymon/handlers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/handlers/__init__.py -------------------------------------------------------------------------------- /celerymon/handlers/api.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from functools import wraps 4 | import itertools 5 | import types 6 | 7 | import anyjson 8 | from tornado.web import RequestHandler, HTTPError 9 | 10 | from celery import states 11 | from celery.task.control import revoke 12 | 13 | from celerymon.state import state 14 | 15 | 16 | def JSON(fun): 17 | 18 | @wraps(fun) 19 | def _write_json(self, *args, **kwargs): 20 | content = fun(self, *args, **kwargs) 21 | if isinstance(content, (types.GeneratorType, itertools.islice)): 22 | content = [c for c in content] 23 | self.write(anyjson.serialize(content)) 24 | 25 | return _write_json 26 | 27 | 28 | class APIHandler(RequestHandler): 29 | 30 | def __init__(self, *args, **kwargs): 31 | super(APIHandler, self).__init__(*args, **kwargs) 32 | self.set_header('Content-Type', 'application/javascript') 33 | 34 | 35 | def api_handler(fun): 36 | 37 | @JSON 38 | def get(self, *args, **kwargs): 39 | return fun(self, *args, **kwargs) 40 | 41 | return type(fun.__name__, (APIHandler, ), {'get': get}) 42 | 43 | 44 | @api_handler 45 | def task_state(request, task_id): 46 | try: 47 | task = state.tasks[task_id.strip('/')] 48 | except KeyError: 49 | raise HTTPError(404, 'Unknown task: %s' % task_id) 50 | if task.state in states.EXCEPTION_STATES: 51 | return task.info(extra=['traceback']) 52 | return task.info() 53 | 54 | 55 | @api_handler 56 | def list_tasks(request): 57 | limit = request.get_argument('limit', None) 58 | limit = limit and int(limit) or None 59 | 60 | since = request.get_argument('since', None) 61 | since = since and int(since) or None 62 | 63 | if not since: 64 | return state.tasks_by_timestamp(limit=limit) 65 | else: 66 | tasks = state.tasks_by_timestamp(limit=limit) 67 | if not tasks: 68 | return [] 69 | tasks_since = [] 70 | for task in tasks: 71 | id, data = task 72 | if data.timestamp > since: 73 | tasks_since.append(task) 74 | else: 75 | return tasks_since 76 | return tasks_since 77 | 78 | 79 | @api_handler 80 | def list_tasks_by_name(request, name): 81 | limit = request.get_argument('limit', None) 82 | limit = limit and int(limit) or None 83 | return state.tasks_by_type(name, limit=limit) 84 | 85 | 86 | @api_handler 87 | def list_task_types(request): 88 | return state.task_types() 89 | 90 | 91 | @api_handler 92 | def list_workers(request): 93 | return state.alive_workers() 94 | 95 | 96 | @api_handler 97 | def show_worker(request, node_name): 98 | try: 99 | return state.workers[node_name] 100 | except KeyError: 101 | raise HTTPError(404, 'Unknown worker node: %s' % node_name) 102 | 103 | 104 | @api_handler 105 | def list_worker_tasks(request, hostname): 106 | limit = request.get_argument('limit', None) 107 | limit = limit and int(limit) or None 108 | return state.tasks_by_worker(hostname, limit=limit) 109 | 110 | 111 | class RevokeTaskHandler(APIHandler): 112 | SUPPORTED_METHODS = ['POST'] 113 | 114 | @JSON 115 | def post(self): 116 | task_id = self.get_argument('task_id') 117 | revoke(task_id) 118 | return {'ok': True} 119 | -------------------------------------------------------------------------------- /celerymon/handlers/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from tornado.web import RequestHandler 4 | 5 | 6 | def handler(fun): 7 | 8 | def get(self, *args, **kwargs): 9 | return fun(self, *args, **kwargs) 10 | 11 | return type(fun.__name__, (RequestHandler, ), {'get': get}) 12 | 13 | 14 | @handler 15 | def index(request): 16 | return request.render('index.html', title='Celery Monitor') 17 | 18 | 19 | @handler 20 | def api_detail(request): 21 | return request.render('api_detail.html', title='API') 22 | -------------------------------------------------------------------------------- /celerymon/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/management/__init__.py -------------------------------------------------------------------------------- /celerymon/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/management/commands/__init__.py -------------------------------------------------------------------------------- /celerymon/management/commands/celerymon.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from djcelery.app import app 4 | from djcelery.management.base import CeleryCommand 5 | 6 | from celerymon.bin.celerymon import MonitorCommand 7 | 8 | monitor = MonitorCommand(app=app) 9 | 10 | 11 | class Command(CeleryCommand): 12 | """Run the celery monitor.""" 13 | option_list = CeleryCommand.option_list + monitor.get_options() 14 | help = 'Run the celery monitor' 15 | 16 | def handle(self, *args, **options): 17 | """Handle the management command.""" 18 | monitor.run(**options) 19 | -------------------------------------------------------------------------------- /celerymon/service.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .consumer import EventConsumer 4 | from .web import WebServerThread 5 | 6 | 7 | class MonitorService(object): 8 | 9 | def __init__(self, logger, http_port=8989, http_address=''): 10 | self.logger = logger 11 | self.http_port = http_port 12 | self.http_address = http_address 13 | 14 | def start(self): 15 | WebServerThread(port=self.http_port, 16 | address=self.http_address).start() 17 | EventConsumer().start() 18 | -------------------------------------------------------------------------------- /celerymon/state.py: -------------------------------------------------------------------------------- 1 | from celery.events.state import State 2 | 3 | # global celerymon state 4 | state = State() 5 | -------------------------------------------------------------------------------- /celerymon/static/analytics.tsv: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | highcharts.com 3 | Daily visits 4 | September 5, 2010 October 5, 2010 5 | # ---------------------------------------- 6 | 7 | # ---------------------------------------- 8 | # Graph 9 | # ---------------------------------------- 10 | Day All Visits (Segment) New Visitors (Segment) 11 | Sunday, September 5, 2010 966 433 12 | Monday, September 6, 2010 2,475 983 13 | Tuesday, September 7, 2010 3,336 1,463 14 | Wednesday, September 8, 2010 3,211 1,316 15 | Thursday, September 9, 2010 3,229 1,351 16 | Friday, September 10, 2010 2,802 1,270 17 | Saturday, September 11, 2010 1,168 604 18 | Sunday, September 12, 2010 1,110 498 19 | Monday, September 13, 2010 3,112 1,352 20 | Tuesday, September 14, 2010 3,590 1,626 21 | Wednesday, September 15, 2010 3,529 1,549 22 | Thursday, September 16, 2010 3,519 1,574 23 | Friday, September 17, 2010 3,696 1,680 24 | Saturday, September 18, 2010 1,400 677 25 | Sunday, September 19, 2010 1,302 603 26 | Monday, September 20, 2010 3,348 1,472 27 | Tuesday, September 21, 2010 3,606 1,570 28 | Wednesday, September 22, 2010 3,320 1,438 29 | Thursday, September 23, 2010 2,677 1,140 30 | Friday, September 24, 2010 2,795 1,256 31 | Saturday, September 25, 2010 1,299 589 32 | Sunday, September 26, 2010 1,189 533 33 | Monday, September 27, 2010 3,189 1,253 34 | Tuesday, September 28, 2010 3,223 1,266 35 | Wednesday, September 29, 2010 3,231 1,249 36 | Thursday, September 30, 2010 3,608 1,684 37 | Friday, October 1, 2010 2,945 1,185 38 | Saturday, October 2, 2010 1,058 460 39 | Sunday, October 3, 2010 1,114 499 40 | Monday, October 4, 2010 2,774 1,131 41 | Tuesday, October 5, 2010 2,679 1,047 42 | 43 | # ---------------------------------------- 44 | # Table 45 | # ---------------------------------------- 46 | Day Visits New Visits 47 | Friday, September 17, 2010 48 | All Visits 3696 1680 49 | New Visitors 1680 1680 50 | % of Total 0.45454545454545453 1.0 51 | Thursday, September 30, 2010 52 | All Visits 3608 1684 53 | New Visitors 1684 1684 54 | % of Total 0.46674057649667405 1.0 55 | Tuesday, September 21, 2010 56 | All Visits 3606 1570 57 | New Visitors 1570 1570 58 | % of Total 0.4353854686633389 1.0 59 | Tuesday, September 14, 2010 60 | All Visits 3590 1626 61 | New Visitors 1626 1626 62 | % of Total 0.452924791086351 1.0 63 | Wednesday, September 15, 2010 64 | All Visits 3529 1549 65 | New Visitors 1549 1549 66 | % of Total 0.4389345423632757 1.0 67 | Thursday, September 16, 2010 68 | All Visits 3519 1574 69 | New Visitors 1574 1574 70 | % of Total 0.44728616084114803 1.0 71 | Monday, September 20, 2010 72 | All Visits 3348 1472 73 | New Visitors 1472 1472 74 | % of Total 0.43966547192353644 1.0 75 | Tuesday, September 7, 2010 76 | All Visits 3336 1463 77 | New Visitors 1463 1463 78 | % of Total 0.4385491606714628 1.0 79 | Wednesday, September 22, 2010 80 | All Visits 3320 1438 81 | New Visitors 1438 1438 82 | % of Total 0.4331325301204819 1.0 83 | Wednesday, September 29, 2010 84 | All Visits 3231 1249 85 | New Visitors 1249 1249 86 | % of Total 0.3865676261219437 1.0 87 | # -------------------------------------------------------------------------------- 88 | -------------------------------------------------------------------------------- /celerymon/static/css/master.css: -------------------------------------------------------------------------------- 1 | body, div, header, ol, ul, li, p, h1, h2, h3, a, img { 2 | margin: 0; padding: 0; border: 0; vertical-align: baseline; list-style: none; 3 | } 4 | 5 | body { 6 | background: #fafafa 50% 0 repeat; 7 | font: 13px/24px "Open Sans", Arial, sans-serif; 8 | color: #444; 9 | } 10 | 11 | .container { 12 | margin: 0 auto; 13 | width: 800px; 14 | box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 15 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04); 16 | -webkit-box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 17 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04); 18 | } 19 | 20 | #maincontent.container { 21 | width: 760px; 22 | padding: 30px 20px 30px 20px; 23 | text-align: left; 24 | background: #fff; 25 | border-radius: 0 0 2px 2px; 26 | box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 27 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04), 28 | 0 1px 1px rgba(0,0,0,0.1), 0 2px 2px rgba(0,0,0,0.05), 0 4px 4px rgba(0,0,0,0.04); 29 | -webkit-box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 30 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04), 31 | 0 1px 1px rgba(0,0,0,0.1), 0 2px 2px rgba(0,0,0,0.05), 0 4px 4px rgba(0,0,0,0.04); 32 | } 33 | 34 | #maincontent.container h1{ 35 | padding-bottom: 8px; 36 | font-size: 32px; 37 | line-height: 32px; 38 | } 39 | 40 | #maincontent.container h2{ 41 | padding-bottom: 5px; 42 | padding-top:10px; 43 | font-weight: bold; 44 | text-transform: none; 45 | } 46 | 47 | #maincontent.container h3{ 48 | padding-bottom: 5px; 49 | padding-top:10px; 50 | } 51 | 52 | #maincontent.container p{ 53 | padding: 2px 0px 5px 0px; 54 | } 55 | 56 | a { 57 | font: inherit; 58 | color: #000; 59 | text-decoration: none; 60 | } 61 | 62 | a:hover { 63 | text-decoration: underline; 64 | } 65 | 66 | h1 { 67 | font-size: 1.8em; 68 | } 69 | 70 | h2 { 71 | font: inherit; 72 | font-size: 1.2em; 73 | color: #000; 74 | text-transform: uppercase; 75 | } 76 | 77 | .contentbox { 78 | text-align: left; 79 | width: 220px; 80 | margin: 10px 15px; 81 | display: inline-block; 82 | vertical-align: top; 83 | } 84 | 85 | .pagination{ 86 | width: 100%; 87 | margin-top: 10px; 88 | margin-bottom: 10px; 89 | } 90 | 91 | .pagination .step-links{ 92 | float: right; 93 | font-size: 12px; 94 | } 95 | 96 | .clear{ 97 | clear: both; 98 | height: 0px; 99 | line-height: 0px; 100 | width: 100%; 101 | } 102 | 103 | #share { 104 | clear: both; 105 | width: 100%; 106 | padding-bottom: 10px; 107 | } 108 | 109 | #share .button{ 110 | float: left; 111 | margin-top: 4px; 112 | } 113 | 114 | div.list { 115 | margin-top: 10px; 116 | } 117 | 118 | div.list .element { 119 | margin-bottom: 20px; 120 | padding-bottom: 10px; 121 | } 122 | 123 | div.list h2{ 124 | font-weight: bold; 125 | } 126 | 127 | ul.small_list .title{ 128 | font-size: 12px; 129 | } 130 | 131 | ul.small_list .meta{ 132 | font-size: 10px; 133 | display: block; 134 | clear: both; 135 | } 136 | 137 | ul.small_list li { 138 | margin-top: 8px; 139 | padding-bottom: 5px; 140 | border-bottom: 1px dotted #ccc; 141 | } 142 | 143 | /* Ze wonderful navigation bar */ 144 | #nav { 145 | background: #e6e6e6; 146 | border-bottom: 1px solid #ccc; 147 | text-align: right; 148 | letter-spacing: -4px; 149 | } 150 | 151 | #nav .container { 152 | background: #eee; 153 | } 154 | 155 | #nav li { 156 | display: inline-block; 157 | letter-spacing: normal; 158 | } 159 | 160 | #nav li a { 161 | color: #666; 162 | text-decoration: none; 163 | text-transform: uppercase; 164 | display: block; 165 | padding: 10px; 166 | background-color: rgba(255,255,255,0); 167 | border-left: 1px solid #ccc; 168 | transition: 0.25s; 169 | -o-transition: 0.25s; 170 | -webkit-transition: 0.25s; 171 | } 172 | 173 | #nav li#home { 174 | float: left; 175 | } 176 | 177 | #nav li#home a { 178 | border-left: 0; 179 | border-right: 1px solid #ccc; 180 | padding: 0 10px 7px; 10px; 181 | } 182 | 183 | #nav li a:hover { 184 | background-color: #fff; 185 | } 186 | 187 | /* Ze wonderful splash area */ 188 | #splash { 189 | background: #e8f0da; 190 | border-bottom: 1px solid #ccc; 191 | color: #454d41; 192 | } 193 | 194 | #splash .container { 195 | background: transparent url(../img/splash.jpg) 0 0 no-repeat; 196 | height: 275px; 197 | } 198 | 199 | #splash h1 { 200 | padding: 40px 70px 10px 250px; 201 | } 202 | 203 | #splash p { 204 | padding: 0 70px 5px 250px; 205 | } 206 | 207 | #splash a { 208 | color: #000; 209 | } 210 | 211 | /* Ze content area */ 212 | #content { 213 | /** text-align: center; **/ 214 | background: #fff; 215 | padding: 25px 0; 216 | } 217 | 218 | #getStarted { 219 | background: #f6faee; 220 | border-radius: 1px; 221 | box-shadow: 0 0 0 10px #f6faee; 222 | } 223 | 224 | /* Ze feeds area */ 225 | #feeds.container { 226 | text-align: center; 227 | background: #fff; 228 | border-radius: 0 0 2px 2px; 229 | box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 230 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04), 231 | 0 1px 1px rgba(0,0,0,0.1), 0 2px 2px rgba(0,0,0,0.05), 0 4px 4px rgba(0,0,0,0.04); 232 | -webkit-box-shadow: 1px 0 rgba(0,0,0,0.1), 2px 0 rgba(0,0,0,0.05), 4px 0 rgba(0,0,0,0.04), 233 | -1px 0 rgba(0,0,0,0.1), -2px 0 rgba(0,0,0,0.05), -4px 0 rgba(0,0,0,0.04), 234 | 0 1px 1px rgba(0,0,0,0.1), 0 2px 2px rgba(0,0,0,0.05), 0 4px 4px rgba(0,0,0,0.04); 235 | } 236 | 237 | #feeds li { 238 | margin-bottom: 1em; 239 | line-height: 1.4em; 240 | } 241 | 242 | #feeds em { 243 | display: block; 244 | font-style: inherit; 245 | } 246 | 247 | 248 | .lastnews li{ 249 | text-align: left; 250 | padding: 0px 32px 0px 32px; 251 | } 252 | 253 | .lastnews h2{ 254 | font-size: 21px; 255 | text-transform: capitalize; 256 | } 257 | 258 | .bigbutton,.bigbutton:visited{ 259 | 260 | background: #222; 261 | display: inline-block; 262 | padding: 5px 10px 6px; 263 | color: #fff; 264 | text-decoration: none; 265 | -moz-border-radius: 6px; 266 | -webkit-border-radius: 6px; 267 | -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6); 268 | -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6); 269 | text-shadow: 0 -1px 1px rgba(0,0,0,0.25); 270 | border-bottom: 1px solid rgba(0,0,0,0.25); 271 | position: relative; 272 | cursor: pointer 273 | 274 | 275 | 276 | } 277 | 278 | /* Ze footer area */ 279 | #footer { 280 | color: #888; 281 | box-shadow: none; 282 | -wekbit-box-shadow: none; 283 | padding: 20px 0; 284 | } 285 | 286 | #footer #credits { 287 | display: inline-block; 288 | width: 390px; 289 | margin: 0 0 0 10px; 290 | vertical-align: top; 291 | font-size: 11px; 292 | } 293 | 294 | #footer #donate { 295 | display: inline-block; 296 | width: 380px; 297 | margin: 0 0 0 10px; 298 | vertical-align: top; 299 | cursor: pointer; 300 | } 301 | 302 | #footer form{ 303 | margin: 0px; 304 | padding: 0px; 305 | } 306 | 307 | #footer #creditcards{ 308 | float: left; 309 | width: 140px; 310 | } 311 | 312 | #footer #creditcards h3{ 313 | padding-bottom: 5px; 314 | } 315 | 316 | #footer #we_welcome{ 317 | float: right; 318 | width: 220px; 319 | } -------------------------------------------------------------------------------- /celerymon/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/static/favicon.ico -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/analytics.tsv: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | highcharts.com 3 | Daily visits 4 | September 5, 2010 October 5, 2010 5 | # ---------------------------------------- 6 | 7 | # ---------------------------------------- 8 | # Graph 9 | # ---------------------------------------- 10 | Day All Visits (Segment) New Visitors (Segment) 11 | Sunday, September 5, 2010 966 433 12 | Monday, September 6, 2010 2,475 983 13 | Tuesday, September 7, 2010 3,336 1,463 14 | Wednesday, September 8, 2010 3,211 1,316 15 | Thursday, September 9, 2010 3,229 1,351 16 | Friday, September 10, 2010 2,802 1,270 17 | Saturday, September 11, 2010 1,168 604 18 | Sunday, September 12, 2010 1,110 498 19 | Monday, September 13, 2010 3,112 1,352 20 | Tuesday, September 14, 2010 3,590 1,626 21 | Wednesday, September 15, 2010 3,529 1,549 22 | Thursday, September 16, 2010 3,519 1,574 23 | Friday, September 17, 2010 3,696 1,680 24 | Saturday, September 18, 2010 1,400 677 25 | Sunday, September 19, 2010 1,302 603 26 | Monday, September 20, 2010 3,348 1,472 27 | Tuesday, September 21, 2010 3,606 1,570 28 | Wednesday, September 22, 2010 3,320 1,438 29 | Thursday, September 23, 2010 2,677 1,140 30 | Friday, September 24, 2010 2,795 1,256 31 | Saturday, September 25, 2010 1,299 589 32 | Sunday, September 26, 2010 1,189 533 33 | Monday, September 27, 2010 3,189 1,253 34 | Tuesday, September 28, 2010 3,223 1,266 35 | Wednesday, September 29, 2010 3,231 1,249 36 | Thursday, September 30, 2010 3,608 1,684 37 | Friday, October 1, 2010 2,945 1,185 38 | Saturday, October 2, 2010 1,058 460 39 | Sunday, October 3, 2010 1,114 499 40 | Monday, October 4, 2010 2,774 1,131 41 | Tuesday, October 5, 2010 2,679 1,047 42 | 43 | # ---------------------------------------- 44 | # Table 45 | # ---------------------------------------- 46 | Day Visits New Visits 47 | Friday, September 17, 2010 48 | All Visits 3696 1680 49 | New Visitors 1680 1680 50 | % of Total 0.45454545454545453 1.0 51 | Thursday, September 30, 2010 52 | All Visits 3608 1684 53 | New Visitors 1684 1684 54 | % of Total 0.46674057649667405 1.0 55 | Tuesday, September 21, 2010 56 | All Visits 3606 1570 57 | New Visitors 1570 1570 58 | % of Total 0.4353854686633389 1.0 59 | Tuesday, September 14, 2010 60 | All Visits 3590 1626 61 | New Visitors 1626 1626 62 | % of Total 0.452924791086351 1.0 63 | Wednesday, September 15, 2010 64 | All Visits 3529 1549 65 | New Visitors 1549 1549 66 | % of Total 0.4389345423632757 1.0 67 | Thursday, September 16, 2010 68 | All Visits 3519 1574 69 | New Visitors 1574 1574 70 | % of Total 0.44728616084114803 1.0 71 | Monday, September 20, 2010 72 | All Visits 3348 1472 73 | New Visitors 1472 1472 74 | % of Total 0.43966547192353644 1.0 75 | Tuesday, September 7, 2010 76 | All Visits 3336 1463 77 | New Visitors 1463 1463 78 | % of Total 0.4385491606714628 1.0 79 | Wednesday, September 22, 2010 80 | All Visits 3320 1438 81 | New Visitors 1438 1438 82 | % of Total 0.4331325301204819 1.0 83 | Wednesday, September 29, 2010 84 | All Visits 3231 1249 85 | New Visitors 1249 1249 86 | % of Total 0.3865676261219437 1.0 87 | # -------------------------------------------------------------------------------- 88 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-basic.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 101 | 102 | 103 | 104 | 105 | 106 |
107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-inverted.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 98 | 99 | 100 | 101 | 102 | 103 |
104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-missing.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 92 | 93 | 94 | 95 | 96 | 97 |
98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-negative.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-stacked-percent.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 89 | 90 | 91 | 92 | 93 | 94 |
95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/area-stacked.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 93 | 94 | 95 | 96 | 97 | 98 |
99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/areaspline.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 92 | 93 | 94 | 95 | 96 | 97 |
98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/bar-basic.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 93 | 94 | 95 | 96 | 97 | 98 |
99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/bar-negative-stack.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 94 | 95 | 96 | 97 | 98 | 99 |
100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/bar-stacked.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-basic.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 104 | 105 | 106 | 107 | 108 | 109 |
110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-drilldown.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 161 | 162 | 163 | 164 | 165 | 166 |
167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-negative.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-parsed.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 90 | 91 | 92 | 93 | 94 | 95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 |
JaneJohn
Apples34
Pears20
Plums511
Bananas11
Oranges24
134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-rotated-labels.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 108 | 109 | 110 | 111 | 112 | 113 |
114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-stacked-and-grouped.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 86 | 87 | 88 | 89 | 90 | 91 |
92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-stacked-percent.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 70 | 71 | 72 | 73 | 74 | 75 |
76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/column-stacked.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 93 | 94 | 95 | 96 | 97 | 98 |
99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/combo-dual-axes.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 108 | 109 | 110 | 111 | 112 | 113 |
114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/combo-multi-axes.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 144 | 145 | 146 | 147 | 148 | 149 |
150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/combo-regression.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 66 | 67 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/combo.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 104 | 105 | 106 | 107 | 108 | 109 |
110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/dynamic-click-to-add.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 95 | 96 | 97 | 98 | 99 | 100 |
101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/dynamic-update.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 104 | 105 | 106 | 107 | 108 | 109 |
110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/line-ajax.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 |
199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/line-basic.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 88 | 89 | 90 | 91 | 92 | 93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/line-labels.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 73 | 74 | 75 | 76 | 77 | 78 |
79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/pie-basic.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 76 | 77 | 78 | 79 | 80 | 81 |
82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/pie-donut.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 155 | 156 | 157 | 158 | 159 | 160 |
161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/pie-legend.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 72 | 73 | 74 | 75 | 76 | 77 |
78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/scatter.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 205 | 206 | 207 | 208 | 209 | 210 |
211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/spline-inverted.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 94 | 95 | 96 | 97 | 98 | 99 |
100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/spline-irregular-time.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 139 | 140 | 141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/spline-plot-bands.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 176 | 177 | 178 | 179 | 180 | 181 |
182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/examples/spline-symbols.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Example 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 94 | 95 | 96 | 97 | 98 | 99 |
100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/exporting-server/index.php: -------------------------------------------------------------------------------- 1 | $output"; 74 | echo "Error while converting SVG"; 75 | } 76 | 77 | // stream it 78 | else { 79 | header("Content-Disposition: attachment; filename=$filename.$ext"); 80 | header("Content-Type: $type"); 81 | echo file_get_contents($outfile); 82 | } 83 | 84 | // delete it 85 | unlink("temp/$tempName.svg"); 86 | unlink($outfile); 87 | 88 | // SVG can be streamed directly back 89 | } else if ($ext == 'svg') { 90 | header("Content-Disposition: attachment; filename=$filename.$ext"); 91 | header("Content-Type: $type"); 92 | echo $svg; 93 | 94 | } else { 95 | echo "Invalid type"; 96 | } 97 | ?> 98 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/graphics/skies.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/static/highcharts/graphics/skies.jpg -------------------------------------------------------------------------------- /celerymon/static/highcharts/graphics/snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/static/highcharts/graphics/snow.png -------------------------------------------------------------------------------- /celerymon/static/highcharts/graphics/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auvipy/celery-flower/dac5d9f0e5547b4eec5501a33eb07d59ae219a1b/celerymon/static/highcharts/graphics/sun.png -------------------------------------------------------------------------------- /celerymon/static/highcharts/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Highcharts Examples 6 | 7 | 8 |

Highcharts Examples

9 |

Line and scatter charts

10 | 30 |

Area charts

31 | 47 |

Column and bar charts

48 | 72 |

Pie charts

73 | 81 |

Dynamic charts

82 | 90 |

Combinations

91 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/js/adapters/mootools-adapter.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v2.1.9 (2011-11-11) 3 | MooTools adapter 4 | 5 | (c) 2010-2011 Torstein H?nsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(){var e=window,h=e.MooTools.version.substring(0,3),i=h==="1.2"||h==="1.1",m=i||h==="1.3",j=e.$extend||function(){return Object.append.apply(Object,arguments)};e.HighchartsAdapter={init:function(a){var b=Fx.prototype,c=b.start,d=Fx.Morph.prototype,g=d.compute;b.start=function(f){var k=this.element;if(f.d)this.paths=a.init(k,k.d,this.toD);c.apply(this,arguments);return this};d.compute=function(f,k,n){var l=this.paths;if(l)this.element.attr("d",a.step(l[0],l[1],n,this.toD));else return g.apply(this, 10 | arguments)}},animate:function(a,b,c){var d=a.attr,g=c&&c.complete;if(d&&!a.setStyle){a.getStyle=a.attr;a.setStyle=function(){var f=arguments;a.attr.call(a,f[0],f[1][0])};a.$family=a.uid=true}e.HighchartsAdapter.stop(a);c=new Fx.Morph(d?a:$(a),j({transition:Fx.Transitions.Quad.easeInOut},c));if(b.d)c.toD=b.d;g&&c.addEvent("complete",g);c.start(b);a.fx=c},each:function(a,b){return i?$each(a,b):a.each(b)},map:function(a,b){return a.map(b)},grep:function(a,b){return a.filter(b)},merge:function(){var a= 11 | arguments,b=[{}],c=a.length;if(i)a=$merge.apply(null,a);else{for(;c--;)if(typeof a[c]!=="boolean")b[c+1]=a[c];a=Object.merge.apply(Object,b)}return a},extendWithEvents:function(a){a.addEvent||(a.nodeName?$(a):j(a,new Events))},addEvent:function(a,b,c){if(typeof b==="string"){if(b==="unload")b="beforeunload";e.HighchartsAdapter.extendWithEvents(a);a.addEvent(b,c)}},removeEvent:function(a,b,c){if(typeof a!=="string"){e.HighchartsAdapter.extendWithEvents(a);if(b){if(b==="unload")b="beforeunload";c?a.removeEvent(b, 12 | c):a.removeEvents(b)}else a.removeEvents()}},fireEvent:function(a,b,c,d){b={type:b,target:a};b=m?new Event(b):new DOMEvent(b);b=j(b,c);b.preventDefault=function(){d=null};a.fireEvent&&a.fireEvent(b.type,b);d&&d(b)},stop:function(a){a.fx&&a.fx.cancel()}}})(); 13 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/js/adapters/mootools-adapter.src.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Highcharts JS v2.1.9 (2011-11-11) 3 | * MooTools adapter 4 | * 5 | * (c) 2010-2011 Torstein Hønsi 6 | * 7 | * License: www.highcharts.com/license 8 | */ 9 | 10 | // JSLint options: 11 | /*global Fx, $, $extend, $each, $merge, Events, Event, DOMEvent */ 12 | 13 | (function () { 14 | 15 | var win = window, 16 | mooVersion = win.MooTools.version.substring(0, 3), // Get the first three characters of the version number 17 | legacy = mooVersion === '1.2' || mooVersion === '1.1', // 1.1 && 1.2 considered legacy, 1.3 is not. 18 | legacyEvent = legacy || mooVersion === '1.3', // In versions 1.1 - 1.3 the event class is named Event, in newer versions it is named DOMEvent. 19 | $extend = win.$extend || function () { 20 | return Object.append.apply(Object, arguments); 21 | }; 22 | 23 | win.HighchartsAdapter = { 24 | /** 25 | * Initialize the adapter. This is run once as Highcharts is first run. 26 | * @param {Object} pathAnim The helper object to do animations across adapters. 27 | */ 28 | init: function (pathAnim) { 29 | var fxProto = Fx.prototype, 30 | fxStart = fxProto.start, 31 | morphProto = Fx.Morph.prototype, 32 | morphCompute = morphProto.compute; 33 | 34 | // override Fx.start to allow animation of SVG element wrappers 35 | /*jslint unparam: true*//* allow unused parameters in fx functions */ 36 | fxProto.start = function (from, to) { 37 | var fx = this, 38 | elem = fx.element; 39 | 40 | // special for animating paths 41 | if (from.d) { 42 | //this.fromD = this.element.d.split(' '); 43 | fx.paths = pathAnim.init( 44 | elem, 45 | elem.d, 46 | fx.toD 47 | ); 48 | } 49 | fxStart.apply(fx, arguments); 50 | 51 | return this; // chainable 52 | }; 53 | 54 | // override Fx.step to allow animation of SVG element wrappers 55 | morphProto.compute = function (from, to, delta) { 56 | var fx = this, 57 | paths = fx.paths; 58 | 59 | if (paths) { 60 | fx.element.attr( 61 | 'd', 62 | pathAnim.step(paths[0], paths[1], delta, fx.toD) 63 | ); 64 | } else { 65 | return morphCompute.apply(fx, arguments); 66 | } 67 | }; 68 | /*jslint unparam: false*/ 69 | }, 70 | 71 | /** 72 | * Animate a HTML element or SVG element wrapper 73 | * @param {Object} el 74 | * @param {Object} params 75 | * @param {Object} options jQuery-like animation options: duration, easing, callback 76 | */ 77 | animate: function (el, params, options) { 78 | var isSVGElement = el.attr, 79 | effect, 80 | complete = options && options.complete; 81 | 82 | if (isSVGElement && !el.setStyle) { 83 | // add setStyle and getStyle methods for internal use in Moo 84 | el.getStyle = el.attr; 85 | el.setStyle = function () { // property value is given as array in Moo - break it down 86 | var args = arguments; 87 | el.attr.call(el, args[0], args[1][0]); 88 | }; 89 | // dirty hack to trick Moo into handling el as an element wrapper 90 | el.$family = el.uid = true; 91 | } 92 | 93 | // stop running animations 94 | win.HighchartsAdapter.stop(el); 95 | 96 | // define and run the effect 97 | effect = new Fx.Morph( 98 | isSVGElement ? el : $(el), 99 | $extend({ 100 | transition: Fx.Transitions.Quad.easeInOut 101 | }, options) 102 | ); 103 | 104 | // special treatment for paths 105 | if (params.d) { 106 | effect.toD = params.d; 107 | } 108 | 109 | // jQuery-like events 110 | if (complete) { 111 | effect.addEvent('complete', complete); 112 | } 113 | 114 | // run 115 | effect.start(params); 116 | 117 | // record for use in stop method 118 | el.fx = effect; 119 | }, 120 | 121 | /** 122 | * MooTool's each function 123 | * 124 | */ 125 | each: function (arr, fn) { 126 | return legacy ? 127 | $each(arr, fn) : 128 | arr.each(fn); 129 | }, 130 | 131 | /** 132 | * Map an array 133 | * @param {Array} arr 134 | * @param {Function} fn 135 | */ 136 | map: function (arr, fn) { 137 | return arr.map(fn); 138 | }, 139 | 140 | /** 141 | * Grep or filter an array 142 | * @param {Array} arr 143 | * @param {Function} fn 144 | */ 145 | grep: function (arr, fn) { 146 | return arr.filter(fn); 147 | }, 148 | 149 | /** 150 | * Deep merge two objects and return a third 151 | */ 152 | merge: function () { 153 | var args = arguments, 154 | args13 = [{}], // MooTools 1.3+ 155 | i = args.length, 156 | ret; 157 | 158 | if (legacy) { 159 | ret = $merge.apply(null, args); 160 | } else { 161 | while (i--) { 162 | // Boolean argumens should not be merged. 163 | // JQuery explicitly skips this, so we do it here as well. 164 | if (typeof args[i] !== 'boolean') { 165 | args13[i + 1] = args[i]; 166 | } 167 | } 168 | ret = Object.merge.apply(Object, args13); 169 | } 170 | 171 | return ret; 172 | }, 173 | 174 | /** 175 | * Extends an object with Events, if its not done 176 | */ 177 | extendWithEvents: function (el) { 178 | // if the addEvent method is not defined, el is a custom Highcharts object 179 | // like series or point 180 | if (!el.addEvent) { 181 | if (el.nodeName) { 182 | el = $(el); // a dynamically generated node 183 | } else { 184 | $extend(el, new Events()); // a custom object 185 | } 186 | } 187 | }, 188 | 189 | /** 190 | * Add an event listener 191 | * @param {Object} el HTML element or custom object 192 | * @param {String} type Event type 193 | * @param {Function} fn Event handler 194 | */ 195 | addEvent: function (el, type, fn) { 196 | if (typeof type === 'string') { // chart broke due to el being string, type function 197 | 198 | if (type === 'unload') { // Moo self destructs before custom unload events 199 | type = 'beforeunload'; 200 | } 201 | 202 | win.HighchartsAdapter.extendWithEvents(el); 203 | 204 | el.addEvent(type, fn); 205 | } 206 | }, 207 | 208 | removeEvent: function (el, type, fn) { 209 | if (typeof el === 'string') { 210 | // el.removeEvents below apperantly calls this method again. Do not quite understand why, so for now just bail out. 211 | return; 212 | } 213 | win.HighchartsAdapter.extendWithEvents(el); 214 | if (type) { 215 | if (type === 'unload') { // Moo self destructs before custom unload events 216 | type = 'beforeunload'; 217 | } 218 | 219 | if (fn) { 220 | el.removeEvent(type, fn); 221 | } else { 222 | el.removeEvents(type); 223 | } 224 | } else { 225 | el.removeEvents(); 226 | } 227 | }, 228 | 229 | fireEvent: function (el, event, eventArguments, defaultFunction) { 230 | var eventArgs = { 231 | type: event, 232 | target: el 233 | }; 234 | // create an event object that keeps all functions 235 | event = legacyEvent ? new Event(eventArgs) : new DOMEvent(eventArgs); 236 | event = $extend(event, eventArguments); 237 | // override the preventDefault function to be able to use 238 | // this for custom events 239 | event.preventDefault = function () { 240 | defaultFunction = null; 241 | }; 242 | // if fireEvent is not available on the object, there hasn't been added 243 | // any events to it above 244 | if (el.fireEvent) { 245 | el.fireEvent(event.type, event); 246 | } 247 | 248 | // fire the default if it is passed and it is not prevented above 249 | if (defaultFunction) { 250 | defaultFunction(event); 251 | } 252 | }, 253 | 254 | /** 255 | * Stop running animations on the object 256 | */ 257 | stop: function (el) { 258 | if (el.fx) { 259 | el.fx.cancel(); 260 | } 261 | } 262 | }; 263 | 264 | }()); 265 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/js/adapters/prototype-adapter.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v2.1.9 (2011-11-11) 3 | Prototype adapter 4 | 5 | @author Michael Nelson, Torstein H?nsi. 6 | 7 | Feel free to use and modify this script. 8 | Highcharts license: www.highcharts.com/license. 9 | */ 10 | var HighchartsAdapter=function(){var g=typeof Effect!=="undefined";return{init:function(c){if(g)Effect.HighchartsTransition=Class.create(Effect.Base,{initialize:function(a,b,d,e){var f;this.element=a;this.key=b;f=a.attr(b);if(b==="d"){this.paths=c.init(a,a.d,d);this.toD=d;f=0;d=1}this.start(Object.extend(e||{},{from:f,to:d,attribute:b}))},setup:function(){HighchartsAdapter._extend(this.element);if(!this.element._highchart_animation)this.element._highchart_animation={};this.element._highchart_animation[this.key]= 11 | this},update:function(a){var b=this.paths;if(b)a=c.step(b[0],b[1],a,this.toD);this.element.attr(this.options.attribute,a)},finish:function(){delete this.element._highchart_animation[this.key]}})},addNS:function(c){var a=/^(?:click|mouse(?:down|up|over|move|out))$/;return/^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/.test(c)||a.test(c)?c:"h:"+c},addEvent:function(c,a,b){if(c.addEventListener||c.attachEvent)Event.observe($(c),HighchartsAdapter.addNS(a),b);else{HighchartsAdapter._extend(c); 12 | c._highcharts_observe(a,b)}},animate:function(c,a,b){var d;b=b||{};b.delay=0;b.duration=(b.duration||500)/1E3;if(g)for(d in a)new Effect.HighchartsTransition($(c),d,a[d],b);else for(d in a)c.attr(d,a[d]);if(!c.attr)throw"Todo: implement animate DOM objects";},stop:function(c){var a;if(c._highcharts_extended&&c._highchart_animation)for(a in c._highchart_animation)c._highchart_animation[a].cancel()},each:function(c,a){$A(c).each(a)},fireEvent:function(c,a,b,d){if(c.fire)c.fire(HighchartsAdapter.addNS(a), 13 | b);else if(c._highcharts_extended){b=b||{};c._highcharts_fire(a,b)}if(b&&b.defaultPrevented)d=null;d&&d(b)},removeEvent:function(c,a,b){if($(c).stopObserving){if(a)a=HighchartsAdapter.addNS(a);$(c).stopObserving(a,b)}if(window===c)Event.stopObserving(c,a,b);else{HighchartsAdapter._extend(c);c._highcharts_stop_observing(a,b)}},grep:function(c,a){return c.findAll(a)},map:function(c,a){return c.map(a)},merge:function(){function c(a,b){var d,e;for(e in b){d=b[e];a[e]=d&&typeof d==="object"&&d.constructor!== 14 | Array&&typeof d.nodeType!=="number"?c(a[e]||{},d):b[e]}return a}return function(){var a=arguments,b,d={};for(b=0;b {a : 'a', b : {b1 : 'b1', b2 : 'b2_prime'}, c : 'c'} 211 | /*merge: function(){ 212 | function doCopy(copy, original) { 213 | var value, 214 | key, 215 | undef, 216 | nil, 217 | same, 218 | obj, 219 | arr, 220 | node; 221 | 222 | for (key in original) { 223 | value = original[key]; 224 | undef = typeof(value) === 'undefined'; 225 | nil = value === null; 226 | same = original === copy[key]; 227 | 228 | if (undef || nil || same) { 229 | continue; 230 | } 231 | 232 | obj = typeof(value) === 'object'; 233 | arr = value && obj && value.constructor == Array; 234 | node = !!value.nodeType; 235 | 236 | if (obj && !arr && !node) { 237 | copy[key] = doCopy(typeof copy[key] == 'object' ? copy[key] : {}, value); 238 | } 239 | else { 240 | copy[key] = original[key]; 241 | } 242 | } 243 | return copy; 244 | } 245 | 246 | var args = arguments, retVal = {}; 247 | 248 | for (var i = 0; i < args.length; i++) { 249 | retVal = doCopy(retVal, args[i]); 250 | } 251 | 252 | return retVal; 253 | },*/ 254 | merge: function () { // the built-in prototype merge function doesn't do deep copy 255 | function doCopy(copy, original) { 256 | var value, key; 257 | 258 | for (key in original) { 259 | value = original[key]; 260 | if (value && typeof value === 'object' && value.constructor !== Array && 261 | typeof value.nodeType !== 'number') { 262 | copy[key] = doCopy(copy[key] || {}, value); // copy 263 | 264 | } else { 265 | copy[key] = original[key]; 266 | } 267 | } 268 | return copy; 269 | } 270 | 271 | function merge() { 272 | var args = arguments, 273 | i, 274 | retVal = {}; 275 | 276 | for (i = 0; i < args.length; i++) { 277 | retVal = doCopy(retVal, args[i]); 278 | 279 | } 280 | return retVal; 281 | } 282 | 283 | return merge.apply(this, arguments); 284 | }, 285 | 286 | // extend an object to handle highchart events (highchart objects, not svg elements). 287 | // this is a very simple way of handling events but whatever, it works (i think) 288 | _extend: function (object) { 289 | if (!object._highcharts_extended) { 290 | Object.extend(object, { 291 | _highchart_events: {}, 292 | _highchart_animation: null, 293 | _highcharts_extended: true, 294 | _highcharts_observe: function (name, fn) { 295 | this._highchart_events[name] = [this._highchart_events[name], fn].compact().flatten(); 296 | }, 297 | _highcharts_stop_observing: function (name, fn) { 298 | if (name) { 299 | if (fn) { 300 | this._highchart_events[name] = [this._highchart_events[name]].compact().flatten().without(fn); 301 | } else { 302 | delete this._highchart_events[name]; 303 | } 304 | } else { 305 | this._highchart_events = {}; 306 | } 307 | }, 308 | _highcharts_fire: function (name, args) { 309 | (this._highchart_events[name] || []).each(function (fn) { 310 | // args is never null here 311 | if (args.stopped) { 312 | return; // "throw $break" wasn't working. i think because of the scope of 'this'. 313 | } 314 | 315 | // Attach a simple preventDefault function to skip default handler if called 316 | args.preventDefault = function () { 317 | args.defaultPrevented = true; 318 | }; 319 | 320 | // If the event handler return false, prevent the default handler from executing 321 | if (fn.bind(this)(args) === false) { 322 | args.preventDefault(); 323 | } 324 | } 325 | .bind(this)); 326 | } 327 | }); 328 | } 329 | } 330 | }; 331 | }()); 332 | -------------------------------------------------------------------------------- /celerymon/static/highcharts/js/modules/exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v2.1.9 (2011-11-11) 3 | Exporting module 4 | 5 | (c) 2010-2011 Torstein H?nsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(){var n=Highcharts,A=n.Chart,B=n.addEvent,E=n.removeEvent,t=n.createElement,w=n.discardElement,u=n.css,x=n.merge,q=n.each,r=n.extend,F=Math.max,s=document,G=window,C=s.documentElement.ontouchstart!==undefined,y=n.getOptions();r(y.lang,{downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",exportButtonTitle:"Export to raster or vector image",printButtonTitle:"Print the chart"});y.navigation={menuStyle:{border:"1px solid #A0A0A0", 10 | background:"#FFFFFF"},menuItemStyle:{padding:"0 5px",background:"none",color:"#303030",fontSize:C?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{align:"right",backgroundColor:{linearGradient:[0,0,0,20],stops:[[0.4,"#F7F7F7"],[0.6,"#E3E3E3"]]},borderColor:"#B0B0B0",borderRadius:3,borderWidth:1,height:20,hoverBorderColor:"#909090",hoverSymbolFill:"#81A7CF",hoverSymbolStroke:"#4572A5",symbolFill:"#E0E0E0",symbolStroke:"#A0A0A0",symbolX:11.5,symbolY:10.5,verticalAlign:"top", 11 | width:24,y:10}};y.exporting={type:"image/png",url:"http://export.highcharts.com/",width:800,enableImages:false,buttons:{exportButton:{symbol:"exportIcon",x:-10,symbolFill:"#A8BF77",hoverSymbolFill:"#768F3E",_id:"exportButton",_titleKey:"exportButtonTitle",menuItems:[{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG", 12 | onclick:function(){this.exportChart({type:"image/svg+xml"})}}]},printButton:{symbol:"printIcon",x:-36,symbolFill:"#B5C9DF",hoverSymbolFill:"#779ABF",_id:"printButton",_titleKey:"printButtonTitle",onclick:function(){this.print()}}}};r(A.prototype,{getSVG:function(b){var c=this,a,f,d,k,e,j,h=x(c.options,b);if(!s.createElementNS)s.createElementNS=function(i,g){var o=s.createElement(g);o.getBBox=function(){return n.Renderer.prototype.Element.prototype.getBBox.apply({element:o})};return o};b=t("div",null, 13 | {position:"absolute",top:"-9999em",width:c.chartWidth+"px",height:c.chartHeight+"px"},s.body);r(h.chart,{renderTo:b,forExport:true});h.exporting.enabled=false;if(!h.exporting.enableImages)h.chart.plotBackgroundImage=null;h.series=[];q(c.series,function(i){d=i.options;d.animation=false;d.showCheckbox=false;d.visible=i.visible;if(!h.exporting.enableImages)if(d&&d.marker&&/^url\(/.test(d.marker.symbol))d.marker.symbol="circle";d.data=[];q(i.data,function(g){k=g.config;e={x:g.x,y:g.y,name:g.name};typeof k=== 14 | "object"&&g.config&&k.constructor!==Array&&r(e,k);e.visible=g.visible;d.data.push(e);if(!h.exporting.enableImages)(j=g.config&&g.config.marker)&&/^url\(/.test(j.symbol)&&delete j.symbol});h.series.push(d)});a=new Highcharts.Chart(h);q(["xAxis","yAxis"],function(i){q(c[i],function(g,o){var l=a[i][o],m=g.getExtremes(),p=m.userMin;m=m.userMax;if(p!==void 0||m!==void 0)l.setExtremes(p,m,true,false)})});f=a.container.innerHTML;h=null;a.destroy();w(b);f=f.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g, 15 | "").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/isTracker="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/]+)/g,'id="$1"').replace(/class=([^" ]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/]*)>/gi,"").replace(/<\/image>/g,"").replace(/]*)([^\/])>/gi, 16 | "").replace(/width=(\d+)/g,'width="$1"').replace(/height=(\d+)/g,'height="$1"').replace(/hc-svg-href="/g,'xlink:href="').replace(/style="([^"]+)"/g,function(i){return i.toLowerCase()});f=f.replace(/(url\(#highcharts-[0-9]+)"/g,"$1").replace(/"/g,"'");if(f.match(/ xmlns="/g).length===2)f=f.replace(/xmlns="[^"]+"/,"");return f},exportChart:function(b,c){var a,f=this.getSVG(c);b=x(this.options.exporting,b);a=t("form",{method:"post",action:b.url},{display:"none"},s.body);q(["filename", 17 | "type","width","svg"],function(d){t("input",{type:"hidden",name:d,value:{filename:b.filename||"chart",type:b.type,width:b.width,svg:f}[d]},null,a)});a.submit();w(a)},print:function(){var b=this,c=b.container,a=[],f=c.parentNode,d=s.body,k=d.childNodes;if(!b.isPrinting){b.isPrinting=true;q(k,function(e,j){if(e.nodeType===1){a[j]=e.style.display;e.style.display="none"}});d.appendChild(c);G.print();setTimeout(function(){f.appendChild(c);q(k,function(e,j){if(e.nodeType===1)e.style.display=a[j]});b.isPrinting= 18 | false},1E3)}},contextMenu:function(b,c,a,f,d,k){var e=this,j=e.options.navigation,h=j.menuItemStyle,i=e.chartWidth,g=e.chartHeight,o="cache-"+b,l=e[o],m=F(d,k),p,z;if(!l){e[o]=l=t("div",{className:"highcharts-"+b},{position:"absolute",zIndex:1E3,padding:m+"px"},e.container);p=t("div",null,r({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},j.menuStyle),l);z=function(){u(l,{display:"none"})};B(l,"mouseleave",z);q(c,function(v){if(v){var D=t("div", 19 | {onmouseover:function(){u(this,j.menuItemHoverStyle)},onmouseout:function(){u(this,h)},innerHTML:v.text||e.options.lang[v.textKey]},r({cursor:"pointer"},h),p);D[C?"ontouchstart":"onclick"]=function(){z();v.onclick.apply(e,arguments)};e.exportDivElements.push(D)}});e.exportDivElements.push(p,l);e.exportMenuWidth=l.offsetWidth;e.exportMenuHeight=l.offsetHeight}b={display:"block"};if(a+e.exportMenuWidth>i)b.right=i-a-d-m+"px";else b.left=a-m+"px";if(f+k+e.exportMenuHeight>g)b.bottom=g-f-m+"px";else b.top= 20 | f+k-m+"px";u(l,b)},addButton:function(b){function c(){g.attr(m);i.attr(l)}var a=this,f=a.renderer,d=x(a.options.navigation.buttonOptions,b),k=d.onclick,e=d.menuItems,j=d.width,h=d.height,i,g,o;b=d.borderWidth;var l={stroke:d.borderColor},m={stroke:d.symbolStroke,fill:d.symbolFill};if(!a.exportDivElements){a.exportDivElements=[];a.exportSVGElements=[]}if(d.enabled!==false){i=f.rect(0,0,j,h,d.borderRadius,b).align(d,true).attr(r({fill:d.backgroundColor,"stroke-width":b,zIndex:19},l)).add();o=f.rect(0, 21 | 0,j,h,0).align(d).attr({id:d._id,fill:"rgba(255, 255, 255, 0.001)",title:a.options.lang[d._titleKey],zIndex:21}).css({cursor:"pointer"}).on("mouseover",function(){g.attr({stroke:d.hoverSymbolStroke,fill:d.hoverSymbolFill});i.attr({stroke:d.hoverBorderColor})}).on("mouseout",c).on("click",c).add();if(e)k=function(){c();var p=o.getBBox();a.contextMenu("export-menu",e,p.x,p.y,j,h)};o.on("click",function(){k.apply(a,arguments)});g=f.symbol(d.symbol,d.symbolX,d.symbolY,(d.symbolSize||12)/2).align(d,true).attr(r(m, 22 | {"stroke-width":d.symbolStrokeWidth||1,zIndex:20})).add();a.exportSVGElements.push(i,o,g)}},destroyExport:function(){var b,c;for(b=0;b 8 | 9 | 147 | 148 | {% end %} 149 | -------------------------------------------------------------------------------- /celerymon/templates/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Celerymon{% end %} | Celery: Distributed Task Queue 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 |
29 | 30 | {% block content %} 31 | 32 |

Celery Real-Time Monitor API

33 | 34 |

/api/task/name/$task_name/?limit=0

35 |

List all tasks by type.

36 | 37 |

/api/task/name/

38 |

List seen task types.

39 | 40 |

/api/task/?limit=0

41 |

List all tasks

42 | 43 |

/api/task/$task_id/

44 |

Show task by UUID.

45 | 46 |

/api/worker/

47 |

List all seen worker nodes.

48 | 49 |

/api/worker/$node_name/tasks/?limit=0

50 |

Show tasks executed by worker.

51 | 52 |

/api/worker/$node_name/

53 |

Show worker status.

54 | 55 | {% end %} 56 | 57 |
58 | 59 |
60 |   61 |
62 | 63 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /celerymon/web.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import os 4 | import threading 5 | 6 | from tornado import httpserver 7 | from tornado import ioloop 8 | from tornado.web import Application, StaticFileHandler 9 | 10 | from .handlers import api, main 11 | 12 | 13 | class WebServerThread(threading.Thread): 14 | 15 | def __init__(self, port=8989, address=''): 16 | super(WebServerThread, self).__init__() 17 | self.port = port 18 | self.address = address 19 | self.setDaemon(True) 20 | 21 | def run(self): 22 | settings = { 23 | 'template_path': os.path.join( 24 | os.path.dirname(__file__), 'templates' 25 | ) 26 | } 27 | 28 | app = Application([ 29 | 30 | # API Endpoints 31 | (r'/api/?$', main.api_detail), 32 | (r'/api/task/name/?$', api.list_task_types), 33 | (r'/api/task/name/(.+?)/?', api.list_tasks_by_name), 34 | (r'/api/task/?', api.list_tasks), 35 | (r'/api/revoke/task/', api.RevokeTaskHandler), 36 | (r'/api/task/(.+)/?', api.task_state), 37 | (r'/api/worker/', api.list_workers), 38 | (r'/api/worker/(.+?)/tasks/?', api.list_worker_tasks), 39 | (r'/api/worker/(.+?)/?', api.show_worker), 40 | 41 | # Static Files 42 | (r'/static/(.*)', StaticFileHandler, { 43 | 'path': os.path.join(os.path.dirname(__file__), 'static'), 44 | }), 45 | 46 | # Web UI Endpoints 47 | (r'/$', main.index), 48 | 49 | ], **settings) 50 | 51 | http_server = httpserver.HTTPServer(app) 52 | http_server.listen(self.port, address=self.address) 53 | ioloop.IOLoop.instance().start() 54 | -------------------------------------------------------------------------------- /requirements/default.txt: -------------------------------------------------------------------------------- 1 | celery>=4.4.0rc3 2 | bareasgi -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import codecs 4 | import os 5 | 6 | try: 7 | from setuptools import setup, find_packages, Command 8 | except ImportError: 9 | from ez_setup import use_setuptools 10 | use_setuptools() 11 | from setuptools import setup, find_packages, Command # noqa 12 | from distutils.command.install import INSTALL_SCHEMES 13 | 14 | import celerymon as distmeta 15 | 16 | packages, data_files = [], [] 17 | root_dir = os.path.dirname(__file__) 18 | if root_dir != '': 19 | os.chdir(root_dir) 20 | src_dir = 'celerymon' 21 | 22 | 23 | def fullsplit(path, result=None): 24 | if result is None: 25 | result = [] 26 | head, tail = os.path.split(path) 27 | if head == '': 28 | return [tail] + result 29 | if head == path: 30 | return result 31 | return fullsplit(head, [tail] + result) 32 | 33 | 34 | for scheme in INSTALL_SCHEMES.values(): 35 | scheme['data'] = scheme['purelib'] 36 | 37 | SKIP_EXTENSIONS = ['.pyc', '.pyo', '.swp', '.swo'] 38 | 39 | 40 | def is_unwanted_file(filename): 41 | for skip_ext in SKIP_EXTENSIONS: 42 | if filename.endswith(skip_ext): 43 | return True 44 | return False 45 | 46 | for dirpath, dirnames, filenames in os.walk(src_dir): 47 | # Ignore dirnames that start with '.' 48 | for i, dirname in enumerate(dirnames): 49 | if dirname.startswith('.'): 50 | del dirnames[i] 51 | for filename in filenames: 52 | if filename.endswith('.py'): 53 | packages.append('.'.join(fullsplit(dirpath))) 54 | elif is_unwanted_file(filename): 55 | pass 56 | else: 57 | data_files.append([dirpath, [os.path.join(dirpath, f) for f in 58 | filenames]]) 59 | 60 | if os.path.exists('README.rst'): 61 | long_description = codecs.open('README.rst', 'r', 'utf-8').read() 62 | else: 63 | long_description = 'See http://pypi.python.org/pypi/celerymon' 64 | 65 | 66 | setup( 67 | name='celerymon', 68 | version=distmeta.__version__, 69 | description=distmeta.__doc__, 70 | author=distmeta.__author__, 71 | author_email=distmeta.__contact__, 72 | url=distmeta.__homepage__, 73 | platforms=['any'], 74 | license='BSD', 75 | packages=packages, 76 | data_files=data_files, 77 | zip_safe=False, 78 | install_requires=[ 79 | 'celery>=4.4.0rc3', 80 | ], 81 | classifiers=[ 82 | 'Development Status :: 5 - Production/Stable', 83 | 'Operating System :: OS Independent', 84 | 'Programming Language :: Python', 85 | 'Programming Language :: Python :: 3.8', 86 | 'Programming Language :: Python :: 3.7', 87 | 'License :: OSI Approved :: BSD License', 88 | 'Operating System :: POSIX', 89 | 'Topic :: System :: Monitoring', 90 | 'Topic :: System :: Distributed Computing', 91 | ], 92 | entry_points={ 93 | 'console_scripts': [ 94 | 'celerymon = celerymon.bin.celerymon:main', 95 | ], 96 | 'celery.commands': [ 97 | 'mon = celerymon.bin.celerymon:MonitorDelegate', 98 | ], 99 | }, 100 | long_description=long_description, 101 | ) 102 | --------------------------------------------------------------------------------