yandex-tank/yandextank/plugins/ApacheBenchmark.py

169 lines
5.6 KiB
Python
Raw Normal View History

''' AB load generator '''
2015-02-02 17:24:32 +00:00
from Aggregator import AggregatorPlugin, AbstractReader
from ConsoleOnline import ConsoleOnlinePlugin, AbstractInfoWidget
import os
2012-09-12 13:18:58 +00:00
import subprocess
2015-02-02 17:24:32 +00:00
from yandextank.core import AbstractPlugin
import yandextank.core as tankcore
2012-09-12 13:18:58 +00:00
class ApacheBenchmarkPlugin(AbstractPlugin):
''' Apache Benchmark plugin '''
2012-09-12 13:18:58 +00:00
SECTION = 'ab'
2015-02-02 17:24:32 +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.out_file = None
self.process = None
2012-10-03 12:44:09 +00:00
self.concurrency = 0
2012-09-26 14:18:17 +00:00
self.options = None
self.url = None
self.requests = None
2012-09-12 13:18:58 +00:00
@staticmethod
def get_key():
2012-10-18 10:46:50 +00:00
return __file__
2015-02-02 17:24:32 +00:00
2013-03-22 13:55:13 +00:00
def get_available_options(self):
return ["options", "url", "requests", "concurrency"]
2015-02-02 17:24:32 +00:00
2012-09-12 13:18:58 +00:00
def configure(self):
2012-09-13 10:19:33 +00:00
self.options = self.get_option("options", '')
self.url = self.get_option("url", 'http://localhost/')
self.requests = self.get_option("requests", '100')
self.concurrency = self.get_option("concurrency", '1')
2012-10-22 11:11:19 +00:00
self.out_file = self.core.mkstemp('.log', 'ab_')
2012-09-12 13:18:58 +00:00
self.core.add_artifact_file(self.out_file)
def prepare_test(self):
aggregator = None
try:
aggregator = self.core.get_plugin_of_type(AggregatorPlugin)
except Exception, ex:
self.log.warning("No aggregator found: %s", ex)
if aggregator:
aggregator.reader = ABReader(aggregator, self)
2015-02-02 17:24:32 +00:00
2012-10-01 11:39:27 +00:00
try:
console = self.core.get_plugin_of_type(ConsoleOnlinePlugin)
except Exception, ex:
self.log.debug("Console not found: %s", ex)
console = None
2015-02-02 17:24:32 +00:00
if console:
2012-10-01 11:39:27 +00:00
widget = ABInfoWidget(self)
console.add_info_widget(widget)
2015-02-02 17:24:32 +00:00
2012-09-12 13:18:58 +00:00
def start_test(self):
2012-09-13 10:45:15 +00:00
args = ['ab', '-r', '-g', self.out_file,
'-n', self.requests,
2012-09-13 10:19:33 +00:00
'-c', self.concurrency, self.url]
self.log.info("Starting ab with arguments: %s", args)
self.process = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
2015-02-02 17:24:32 +00:00
2012-09-12 13:18:58 +00:00
def is_test_finished(self):
retcode = self.process.poll()
if retcode != None:
self.log.debug("%s exit code: %s", self.SECTION, retcode)
return retcode
2012-09-12 13:18:58 +00:00
else:
return -1
2015-02-02 17:24:32 +00:00
2012-09-12 16:48:22 +00:00
def end_test(self, retcode):
2014-06-10 14:47:35 +00:00
if self.process and self.process.poll() is None:
2012-09-12 13:18:58 +00:00
self.log.warn("Terminating ab process with PID %s", self.process.pid)
self.process.terminate()
else:
self.log.info("Seems ab finished OK")
2012-09-12 13:18:58 +00:00
if self.process:
2012-10-03 16:49:13 +00:00
tankcore.log_stdout_stderr(self.log, self.process.stdout, self.process.stderr, self.SECTION)
2012-09-12 16:48:22 +00:00
return retcode
2012-09-12 13:18:58 +00:00
2015-02-02 17:24:32 +00:00
2012-09-20 06:55:45 +00:00
class ABReader(AbstractReader):
'''
Adapter to read AB files
'''
def __init__(self, aggregator, abench):
AbstractReader.__init__(self, aggregator)
self.abench = abench
self.results = None
2015-02-02 17:24:32 +00:00
def check_open_files(self):
if not self.results and os.path.exists(self.abench.out_file):
self.log.debug("Opening ab out file: %s", self.abench.out_file)
self.results = open(self.abench.out_file, 'r')
2015-02-02 17:24:32 +00:00
2012-10-22 11:11:19 +00:00
def close_files(self):
if self.results:
self.results.close()
2015-02-02 17:24:32 +00:00
def get_next_sample(self, force):
if self.results:
read_lines = self.results.readlines()
if read_lines:
2013-03-22 13:55:13 +00:00
read_lines.pop(0) # remove header line
self.log.debug("About to process %s result lines", len(read_lines))
for line in read_lines:
line = line.strip()
if not line:
2015-02-02 17:24:32 +00:00
return None
2013-03-22 13:55:13 +00:00
# Tue Sep 25 14:19:36 2012 1348568376 0 36 36 34
data = line.split("\t")
if len(data) != 6:
self.log.warning("Wrong ab log line, skipped: %s", line)
continue
cur_time = int(data[1])
ctime = int(data[2])
2013-03-22 13:55:13 +00:00
# dtime = int(data[3])
ttime = int(data[4])
wait = int(data[5])
2015-02-02 17:24:32 +00:00
if not cur_time in self.data_buffer.keys():
self.data_queue.append(cur_time)
self.data_buffer[cur_time] = []
# marker, threads, overallRT, httpCode, netCode
2012-10-23 17:30:53 +00:00
data_item = ['', self.abench.concurrency, ttime, 0, 0]
# bytes: sent received
data_item += [0, 0]
# connect send latency receive
data_item += [ctime, 0, wait, ttime - ctime - wait]
# accuracy
data_item += [0]
self.data_buffer[cur_time].append(data_item)
2015-02-02 17:24:32 +00:00
if self.data_queue:
return self.pop_second()
else:
2015-02-02 17:24:32 +00:00
return None
2012-10-01 11:39:27 +00:00
class ABInfoWidget(AbstractInfoWidget):
2015-02-02 17:24:32 +00:00
''' Console widget '''
def __init__(self, abench):
2012-10-01 11:39:27 +00:00
AbstractInfoWidget.__init__(self)
self.abench = abench
2012-10-01 11:39:27 +00:00
self.active_threads = 0
def get_index(self):
return 0
2015-02-02 17:24:32 +00:00
def render(self, screen):
2012-10-01 11:39:27 +00:00
ab_text = " Apache Benchmark Test "
2015-02-02 17:24:32 +00:00
space = screen.right_panel_width - len(ab_text) - 1
2012-10-01 11:39:27 +00:00
left_spaces = space / 2
right_spaces = space / 2
2015-02-02 17:24:32 +00:00
template = screen.markup.BG_BROWN + '~' * left_spaces + ab_text + ' ' + '~' * right_spaces + screen.markup.RESET + "\n"
2012-10-01 11:39:27 +00:00
template += " URL: %s\n"
template += " Concurrency: %s\n"
template += "Total Requests: %s"
data = (self.abench.url, self.abench.concurrency, self.abench.requests)
2015-02-02 17:24:32 +00:00
2012-10-01 11:39:27 +00:00
return template % data