yandex-tank/yandextank/plugins/ConsoleOnline.py

180 lines
5.5 KiB
Python
Raw Normal View History

''' Plugin provides fullscreen console '''
import logging
2012-10-03 16:49:13 +00:00
import sys
import traceback
2014-12-06 07:33:41 +00:00
import threading
2014-02-11 10:21:14 +00:00
2015-02-02 17:24:32 +00:00
from Aggregator import AggregatorPlugin, AggregateResultListener
from ConsoleScreen import Screen
from yandextank.core import AbstractPlugin
2014-02-11 10:21:14 +00:00
2012-09-12 13:18:58 +00:00
class ConsoleOnlinePlugin(AbstractPlugin, AggregateResultListener):
''' Console plugin '''
2012-09-12 13:18:58 +00:00
SECTION = 'console'
2014-02-11 10:21:14 +00:00
2012-09-12 13:18:58 +00:00
def __init__(self, core):
2012-09-13 10:19:33 +00:00
AbstractPlugin.__init__(self, core)
2012-09-12 13:18:58 +00:00
self.screen = None
self.render_exception = None
2012-10-03 12:37:15 +00:00
self.console_markup = None
self.remote_translator = None
self.info_panel_width = '33'
self.short_only = 0
2014-12-06 07:33:41 +00:00
# these three provide non-blocking console output
self.__console_view = None
self.__writer_thread = None
self.__writer_event = None
2012-09-12 13:18:58 +00:00
@staticmethod
def get_key():
return __file__
2014-02-11 10:21:14 +00:00
2013-03-22 13:55:13 +00:00
def get_available_options(self):
return ["info_panel_width", "short_only", "disable_all_colors", "disable_colors"]
2014-02-11 10:21:14 +00:00
2012-09-12 13:18:58 +00:00
def configure(self):
self.info_panel_width = self.get_option("info_panel_width", self.info_panel_width)
2012-09-13 10:19:33 +00:00
self.short_only = int(self.get_option("short_only", '0'))
if not int(self.get_option("disable_all_colors", '0')):
self.console_markup = RealConsoleMarkup()
else:
self.console_markup = NoConsoleMarkup()
for color in self.get_option("disable_colors", '').split(' '):
self.console_markup.__dict__[color] = ''
self.screen = Screen(self.info_panel_width, self.console_markup)
2012-10-03 12:37:15 +00:00
2012-10-22 11:11:19 +00:00
try:
aggregator = self.core.get_plugin_of_type(AggregatorPlugin)
aggregator.add_result_listener(self)
except KeyError:
self.log.debug("No aggregator for console")
self.screen.block_rows = []
self.screen.info_panel_percent = 100
2012-10-22 11:11:19 +00:00
2014-12-06 07:33:41 +00:00
def __console_writer(self):
while True:
self.__writer_event.wait()
self.__writer_event.clear()
if self.__console_view:
if not self.short_only:
self.log.debug("Writing console view to STDOUT")
sys.stdout.write(self.console_markup.clear)
sys.stdout.write(self.__console_view)
sys.stdout.write(self.console_markup.TOTAL_RESET)
if self.remote_translator:
self.remote_translator.send_console(console_view)
2012-09-20 06:55:45 +00:00
def is_test_finished(self):
2014-12-06 07:33:41 +00:00
if not self.__writer_thread:
self.__writer_event = threading.Event()
self.__writer_thread = threading.Thread(target=self.__console_writer)
self.__writer_thread.daemon = True
self.__writer_thread.start()
try:
2014-12-06 07:33:41 +00:00
self.__console_view = self.screen.render_screen().encode('utf-8')
except Exception, ex:
self.log.warn("Exception inside render: %s", traceback.format_exc(ex))
self.render_exception = ex
2014-12-06 07:33:41 +00:00
self.__console_view = ""
2012-09-12 13:18:58 +00:00
2014-12-06 07:33:41 +00:00
self.__writer_event.set()
2012-09-20 06:55:45 +00:00
return -1
2014-02-11 10:21:14 +00:00
2012-09-20 06:55:45 +00:00
def aggregate_second(self, second_aggregate_data):
2014-02-11 10:21:14 +00:00
self.screen.add_second_data(second_aggregate_data)
2012-09-20 06:55:45 +00:00
if self.short_only:
tpl = "Time: %s\tExpected RPS: %s\tActual RPS: %s\tActive Threads: %s\tAvg RT: %s"
2013-03-22 13:55:13 +00:00
ovr = second_aggregate_data.overall # just to see the next line in IDE
data = (second_aggregate_data.time, ovr.planned_requests, ovr.RPS,
ovr.active_threads, ovr.avg_response_time)
2012-09-20 06:55:45 +00:00
self.log.info(tpl % data)
2014-02-11 10:21:14 +00:00
2012-09-12 13:18:58 +00:00
def add_info_widget(self, widget):
''' add right panel widget '''
2012-09-12 13:18:58 +00:00
if not self.screen:
2012-10-18 10:46:50 +00:00
self.log.debug("No screen instance to add widget")
2012-09-12 13:18:58 +00:00
else:
self.screen.add_info_widget(widget)
2014-02-11 10:21:14 +00:00
2012-10-03 12:37:15 +00:00
# ======================================================
2012-10-03 12:37:15 +00:00
class RealConsoleMarkup(object):
2015-02-02 17:24:32 +00:00
'''
2012-10-03 12:37:15 +00:00
Took colors from here: https://www.siafoo.net/snippet/88
'''
WHITE_ON_BLACK = '\033[37;40m'
TOTAL_RESET = '\033[0m'
clear = "\x1b[2J\x1b[H"
2014-02-11 10:21:14 +00:00
new_line = u"\n"
2012-10-03 12:37:15 +00:00
YELLOW = '\033[1;33m'
RED = '\033[1;31m'
RED_DARK = '\033[31;3m'
RESET = '\033[1;m'
CYAN = "\033[1;36m"
GREEN = "\033[1;32m"
WHITE = "\033[1;37m"
MAGENTA = '\033[1;35m'
BG_MAGENTA = '\033[1;45m'
BG_GREEN = '\033[1;42m'
BG_BROWN = '\033[1;43m'
BG_CYAN = '\033[1;46m'
2014-02-11 10:21:14 +00:00
2012-10-03 12:37:15 +00:00
def clean_markup(self, orig_str):
''' clean markup from string '''
2012-10-03 12:37:15 +00:00
for val in [self.YELLOW, self.RED, self.RESET,
self.CYAN, self.BG_MAGENTA, self.WHITE,
self.BG_GREEN, self.GREEN, self.BG_BROWN,
self.RED_DARK, self.MAGENTA, self.BG_CYAN]:
orig_str = orig_str.replace(val, '')
return orig_str
2014-02-11 10:21:14 +00:00
2012-10-03 12:37:15 +00:00
# ======================================================
2012-10-03 12:59:46 +00:00
# FIXME: 3 better way to have it?
2012-10-03 12:37:15 +00:00
class NoConsoleMarkup(RealConsoleMarkup):
''' all colors are disabled '''
2012-10-03 12:37:15 +00:00
WHITE_ON_BLACK = ''
TOTAL_RESET = ''
clear = ""
2014-02-11 10:21:14 +00:00
new_line = u"\n"
2012-10-03 12:37:15 +00:00
YELLOW = ''
RED = ''
RED_DARK = ''
RESET = ''
CYAN = ""
GREEN = ""
WHITE = ""
MAGENTA = ''
BG_MAGENTA = ''
BG_GREEN = ''
BG_BROWN = ''
BG_CYAN = ''
2014-02-11 10:21:14 +00:00
2012-10-03 12:37:15 +00:00
# ======================================================
class AbstractInfoWidget:
''' parent class for all right panel widgets '''
2014-02-11 10:21:14 +00:00
2012-10-03 12:37:15 +00:00
def __init__(self):
self.log = logging.getLogger(__name__)
def render(self, screen):
2012-10-25 14:12:24 +00:00
raise NotImplementedError()
2012-10-03 12:37:15 +00:00
def get_index(self):
''' get vertical priority index '''
return 0