Commit b7f7c296 authored by Daniele Venzano's avatar Daniele Venzano

Add a statistics API to retrieve scheduler status

parent 6c559ffb
......@@ -137,6 +137,12 @@ class APIEndpoint:
swarm = SwarmClient(get_conf())
return swarm.logs(service.docker_id, stream)
def statistics_scheduler(self, uid_, role_):
"""Retrieve statistics about the scheduler."""
success, message = self.master.scheduler_statistics()
if success:
return message
def retry_submit_error_executions(self):
"""Resubmit any execution forgotten by the master."""
waiting_execs = self.sql.execution_list(status=zoe_lib.sql_manager.Execution.SUBMIT_STATUS)
......
......@@ -100,3 +100,10 @@ class APIManager:
'exec_id': exec_id
}
return self._request_reply(msg)
def scheduler_statistics(self) -> APIReturnType:
"""Query scheduler statistics."""
msg = {
'command': 'scheduler_stats'
}
return self._request_reply(msg)
......@@ -23,6 +23,7 @@ from zoe_api.rest_api.execution import ExecutionAPI, ExecutionCollectionAPI, Exe
from zoe_api.rest_api.info import InfoAPI
from zoe_api.rest_api.service import ServiceAPI, ServiceLogsAPI
from zoe_api.rest_api.discovery import DiscoveryAPI
from zoe_api.rest_api.statistics import SchedulerStatsAPI
from zoe_lib.version import ZOE_API_VERSION
......@@ -45,7 +46,9 @@ def api_init(api_endpoint) -> List[tornado.web.URLSpec]:
tornado.web.url(API_PATH + r'/service/([0-9]+)', ServiceAPI, route_args),
tornado.web.url(API_PATH + r'/service/logs/([0-9]+)', ServiceLogsAPI, route_args),
tornado.web.url(API_PATH + r'/discovery/by_group/([0-9]+)/([a-z0-9A-Z\-]+)', DiscoveryAPI, route_args)
tornado.web.url(API_PATH + r'/discovery/by_group/([0-9]+)/([a-z0-9A-Z\-]+)', DiscoveryAPI, route_args),
tornado.web.url(API_PATH + r'/statistics/scheduler', SchedulerStatsAPI, route_args)
]
return api_routes
# Copyright (c) 2016, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Scheduler Statistics API endpoint."""
from tornado.web import RequestHandler
from zoe_api.api_endpoint import APIEndpoint # pylint: disable=unused-import
from zoe_api.rest_api.utils import catch_exceptions
class SchedulerStatsAPI(RequestHandler):
"""The Scheduler Statistics API endpoint."""
def initialize(self, **kwargs):
"""Initializes the request handler."""
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self):
"""HTTP GET method."""
statistics = self.api_endpoint.statistics_scheduler(0, 'guest')
self.write(statistics)
def data_received(self, chunk):
"""Not implemented as we do not use stream uploads"""
pass
......@@ -28,6 +28,7 @@ from typing import Tuple
from zoe_cmd import utils
from zoe_lib.info import ZoeInfoAPI
from zoe_lib.services import ZoeServiceAPI
from zoe_lib.statistics import ZoeStatisticsAPI
from zoe_lib.exceptions import ZoeAPIException, InvalidApplicationDescription
from zoe_lib.executions import ZoeExecutionsAPI
from zoe_lib.applications import app_validate
......@@ -142,6 +143,14 @@ def logs_cmd(args):
except KeyboardInterrupt:
print('CTRL-C detected, exiting...')
def stats_cmd(args_):
"""Prints statistics on Zoe internals."""
stats_api = ZoeStatisticsAPI(utils.zoe_url(), utils.zoe_user(), utils.zoe_pass())
sched = stats_api.scheduler()
print('Scheduler queue length: {}'.format(sched['queue_length']))
print('Termination threads count: {}'.format(sched['termination_threads_count']))
ENV_HELP_TEXT = '''To use this tool you need also to define three environment variables:
ZOE_URL: point to the URL of the Zoe Scheduler (ex.: http://localhost:5000/
ZOE_USER: the username used for authentication
......@@ -191,6 +200,9 @@ def process_arguments() -> Tuple[ArgumentParser, Namespace]:
argparser_logs.add_argument('-t', '--timestamps', action='store_true', help="Prefix timestamps for each line")
argparser_logs.set_defaults(func=logs_cmd)
argparser_stats = subparser.add_parser('stats', help="Prints all available statistics")
argparser_stats.set_defaults(func=stats_cmd)
return parser, parser.parse_args()
......
# Copyright (c) 2016, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
This module contains the Zoe Statistics API.
"""
import logging
from zoe_lib.api_base import ZoeAPIBase
from zoe_lib.exceptions import ZoeAPIException
log = logging.getLogger(__name__)
class ZoeStatisticsAPI(ZoeAPIBase):
"""
The Statistics API class. This API exports dynamic information about Zoe inner status and counters.
"""
def scheduler(self):
"""
Queries Zoe for scheduler statistics.
:return:
"""
data, status_code = self._rest_get('/statistics/scheduler')
if status_code != 200:
raise ZoeAPIException(data['message'])
else:
return data
......@@ -86,6 +86,9 @@ class APIManager:
if execution is not None:
zoe_master.execution_manager.execution_delete(self.scheduler, execution)
self._reply_ok()
elif message['command'] == 'scheduler_stats':
data = self.scheduler.stats()
self._reply_ok(data=data)
else:
log.error('Unknown command: {}'.format(message['command']))
self._reply_error('unknown command')
......
......@@ -128,3 +128,11 @@ class ZoeScheduler:
self.loop_quit = True
self.trigger()
self.loop_th.join()
def stats(self):
"""Scheduler statistics."""
return {
'queue_length': len(self.fifo_queue),
'termination_threads_count': len(self.async_threads)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment