From 9b292b3699b44dce3330f060a7838613cbe5f1c0 Mon Sep 17 00:00:00 2001 From: Yuriy Gorishniy Date: Sat, 20 May 2017 16:49:09 +0300 Subject: [PATCH 1/2] add new page for displaying statistics --- everware/__init__.py | 1 + everware/stats_handler.py | 42 ++++++++++++++++++++++++++++++++++++++++++ everware/user_spawn_handler.py | 16 ++++++++++++++++ scripts/everware-server | 28 +++++++++++++++++++++------- share/static/html/stats.html | 10 ++++++++++ 5 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 everware/stats_handler.py create mode 100644 share/static/html/stats.html diff --git a/everware/__init__.py b/everware/__init__.py index 64c6479..478fe31 100755 --- a/everware/__init__.py +++ b/everware/__init__.py @@ -4,3 +4,4 @@ from .user_spawn_handler import * from .user_wait_handler import * from .home_handler import * +from .stats_handler import * diff --git a/everware/stats_handler.py b/everware/stats_handler.py new file mode 100644 index 0000000..7a218dc --- /dev/null +++ b/everware/stats_handler.py @@ -0,0 +1,42 @@ +from jupyterhub.handlers.pages import BaseHandler +from docker import Client +from tornado import gen + + +class StatsHandler(BaseHandler): + """Handler for the stats page ['/hub/stats']. + + Fills the page with some statistics on everware. + """ + container_statuses = { + 'running': 'running', + 'restarting': 'restarting', + 'paused': 'paused', + 'exited': 'exited' + } + + def initialize(self, stats): + """Initialize the handler. + + Parameters + ---------- + stats : dict + A dict containing all the stats on the everware instance. + """ + self.stats = stats + + @gen.coroutine + def get(self, *args, **kwargs): + running_container_count = yield self.get_running_container_count() + html = self.render_template( + 'stats.html', + running_container_count=running_container_count, + total_launch_count=self.stats['total_launch_count'] + ) + self.finish(html) + + @gen.coroutine + def get_running_container_count(self): + """Get the number of currently running containers.""" + return len(Client().containers( + filters={'status': self.container_statuses['running']})) diff --git a/everware/user_spawn_handler.py b/everware/user_spawn_handler.py index 96d7101..c09bb55 100755 --- a/everware/user_spawn_handler.py +++ b/everware/user_spawn_handler.py @@ -5,8 +5,22 @@ from . import __version__ from .metrica import MetricaIdsMixin + class SpawnHandler(default_handlers.SpawnHandler): + def initialize(self, stats): + """Initialize the handler. + + Collect reference to the everware instance stats for incrementing + the field 'total_launch_count'. + + Parameters + ---------- + stats : dict + A dict containing the key 'total_launch_count'. + """ + self.stats = stats + def _render_form(self, message=''): user = self.get_current_user() metrica = MetricaIdsMixin() @@ -39,6 +53,8 @@ def _spawn(self, user, form_options): user.token = user.spawner.token except Exception as e: self.log.error("Failed to spawn single-user server with form", exc_info=True) + else: + self.stats['total_launch_count'] += 1 @web.authenticated def get(self): diff --git a/scripts/everware-server b/scripts/everware-server index 5afc66c..f303004 100755 --- a/scripts/everware-server +++ b/scripts/everware-server @@ -2,7 +2,7 @@ import jupyterhub.handlers.pages as pages import jupyterhub.handlers.base as base from jupyterhub import app -from everware import SpawnHandler, UserSpawnHandler, HomeHandler +from everware import SpawnHandler, UserSpawnHandler, HomeHandler, StatsHandler import sys import warnings @@ -10,17 +10,31 @@ import warnings class Everware(app.JupyterHub): name = 'everware' - custom_handlers = [ - ('/hub/user/([^/]+)(/.*)?', UserSpawnHandler), - ('/hub/home', HomeHandler), - ('/hub/spawn', SpawnHandler) - ] + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.stats = { + 'total_launch_count': 0 + } def init_handlers(self): super().init_handlers() - self.add_handlers(Everware.custom_handlers) + self.add_handlers([ + ('/hub/user/([^/]+)(/.*)?', UserSpawnHandler), + ('/hub/home', HomeHandler), + ('/hub/spawn', SpawnHandler, {'stats': self.stats}), + ('/hub/stats', StatsHandler, {'stats': self.stats}) + ]) def add_handlers(self, handlers, replace_existing=True): + """Add new handlers. + + Parameters + ---------- + handlers : list-like + Contains tuples representing handlers: (url, handler[, init_args]). + replace_existing : bool, optional(True) + If True, old handlers will be overwritten by new ones on overlapping urls. + """ existing_handler_indices = {handler[0]: i for i, handler in enumerate(self.handlers)} for handler in handlers: existing_handler_index = existing_handler_indices.get(handler[0]) diff --git a/share/static/html/stats.html b/share/static/html/stats.html new file mode 100644 index 0000000..f85046c --- /dev/null +++ b/share/static/html/stats.html @@ -0,0 +1,10 @@ +{% extends "page.html" %} + +{% block main %} +

+ Currently running containers: {{ running_container_count }} +

+

+ Total number of launches: {{ total_launch_count }} +

+{% endblock %} From 042f8092edc32d3a3530709551a5a5da18a017f0 Mon Sep 17 00:00:00 2001 From: Yuriy Gorishniy Date: Sat, 10 Jun 2017 16:20:12 +0300 Subject: [PATCH 2/2] increment everware version --- everware/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/everware/__init__.py b/everware/__init__.py index 478fe31..6243a2c 100755 --- a/everware/__init__.py +++ b/everware/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.10.1" +__version__ = "0.11.0" from .spawner import * from .authenticator import * from .user_spawn_handler import *