def prepare(self): super(ApiritifNoseExecutor, self).prepare() self.script = self.get_script_path() if not self.script: if "requests" in self.get_scenario(): self.script = self.__tests_from_requests() else: raise TaurusConfigError( "Nothing to test, no requests were provided in scenario") # todo: requred tools? # path to taurus dir. It's necessary for bzt usage inside tools/helpers self.env.add_path({"PYTHONPATH": get_full_path(BZT_DIR, step_up=1)}) self.reporting_setup( ) # no prefix/suffix because we don't fully control report file names
def __init__(self, config, scenario, engine, pure_body_file=False): self.engine = engine self.log = self.engine.log.getChild(self.__class__.__name__) super(HTTPRequest, self).__init__(config, scenario) msg = "Option 'url' is mandatory for request but not found in %s" % config self.url = self.config.get("url", TaurusConfigError(msg)) self.label = str(self.config.get("label", self.url)) self.method = self.config.get("method", "GET") if not has_variable_pattern(self.method): self.method = self.method.upper() self.headers = self.config.get("headers", {}) self.keepalive = self.config.get('keepalive', None) self.timeout = self.config.get('timeout', None) self.follow_redirects = self.config.get('follow-redirects', None) self.body = self._get_body(pure_body_file=pure_body_file)
def prepare(self): super(Proxy2JMX, self).prepare() self.address = self.settings.get('address', self.address) token = self.settings.get('token') if not token: token = self.engine.config.get('modules').get('blazemeter').get( 'token') if not token: msg = "You must provide your API token in settings of " \ "'proxy2jmx' or 'blazemeter' modules to use Proxy Recorder" raise TaurusConfigError(msg) self.headers = {"X-Api-Key": token} # todo: handle network exceptions (ssl, ...) in next call self.proxy = self.__get_proxy()
def prepare(self): """ Preparation in provisioning begins with reading executions list and instantiating ScenarioExecutor classes for them """ super(Provisioning, self).prepare() exc = TaurusConfigError("No 'execution' is configured. Did you forget to pass config files?") executions = self.engine.config.get(EXEC, []) if not executions and self.disallow_empty_execution: raise exc for execution in executions: instance = self.engine.instantiate_module(execution.get("executor")) instance.provisioning = self instance.execution = execution self.executors.append(instance)
def apply_load_profile(self, load): # do not apply unspecified load profile if not load.concurrency and not load.hold: return original_load = self.find("//tsung/load") generated_load = self.__gen_load(load) if not original_load: self.log.warning( "<load> section not found in Tsung config, will create one") servers = self.find("//tsung/servers") if not servers: raise TaurusConfigError( "Provided Tsung script is invalid: <servers> section not found" ) servers.addnext(generated_load) else: self.root.replace(original_load[0], generated_load)
def __init__(self, config, scenario, engine): self.engine = engine self.log = self.engine.log.getChild(self.__class__.__name__) super(HTTPRequest, self).__init__(config, scenario) msg = "Option 'url' is mandatory for request but not found in %s" % config self.url = self.config.get("url", TaurusConfigError(msg)) self.label = self.config.get("label", self.url) self.method = self.config.get("method", "GET") # TODO: add method to join dicts/lists from scenario/request level? self.headers = self.config.get("headers", {}) self.keepalive = self.config.get('keepalive', None) self.timeout = self.config.get('timeout', None) self.think_time = self.config.get('think-time', None) self.follow_redirects = self.config.get('follow-redirects', None) self.body = self.__get_body()
def __init__(self, config, parent_log, working_dir, env): """ :type env: Environment """ self.log = parent_log.getChild(self.__class__.__name__) self.working_dir = working_dir self.env = env self.command = config.get( "command", TaurusConfigError("Parameter is required: command")) self.is_background = config.get("background", False) self.out = config.get("out", None) self.err = config.get("err", None) self.ignore_failure = config.get("ignore-failure", False) self.process = None
def __configure(self, configs): self.log.info("Starting with configs: %s", configs) if self.options.no_system_configs is None: self.options.no_system_configs = False bzt_rc = os.path.expanduser(os.path.join('~', ".bzt-rc")) if os.path.exists(bzt_rc): self.log.debug("Using personal config: %s" % bzt_rc) else: self.log.debug("Adding personal config: %s", bzt_rc) self.log.info("No personal config found, creating one at %s", bzt_rc) shutil.copy( os.path.join(get_full_path(__file__, step_up=1), 'resources', 'base-bzt-rc.yml'), bzt_rc) merged_config = self.engine.configure( [bzt_rc] + configs, not self.options.no_system_configs) # apply aliases for alias in self.options.aliases: cli_aliases = self.engine.config.get('cli-aliases') keys = sorted(cli_aliases.keys()) err = TaurusConfigError( "'%s' not found in aliases. Available aliases are: %s" % (alias, ", ".join(keys))) self.engine.config.merge(cli_aliases.get(alias, err)) if self.options.option: overrider = ConfigOverrider(self.log) overrider.apply_overrides(self.options.option, self.engine.config) settings = self.engine.config.get(SETTINGS) settings.get('verbose', bool(self.options.verbose)) # respect value from config if self.options.verbose: # force verbosity if cmdline asked for it settings['verbose'] = True if settings.get('verbose'): CLI.console_handler.setLevel(logging.DEBUG) self.engine.create_artifacts_dir(configs, merged_config) self.engine.default_cwd = os.getcwd() self.engine.eval_env( ) # yacky, I don't like having it here, but how to apply it after aliases and artif dir?
def prepare(self): self.install_required_tools() scenario = self.get_scenario() jar_files = [] files = self.execution.get('files', []) for candidate in files: candidate = get_full_path(self.engine.find_file(candidate)) if os.path.isfile(candidate) and candidate.lower().endswith( '.jar'): jar_files.append(candidate) elif os.path.isdir(candidate): for element in os.listdir(candidate): element = os.path.join(candidate, element) if os.path.isfile(element) and element.lower().endswith( '.jar'): jar_files.append(element) self.log.debug("JAR files list for Gatling: %s", jar_files) if jar_files: separator = os.pathsep self.jar_list = separator + separator.join(jar_files) if is_windows() or jar_files: self.log.debug("Building Gatling launcher") self.launcher = self.__build_launcher() else: self.log.debug("Will not build Gatling launcher") self.launcher = self.settings["path"] if Scenario.SCRIPT in scenario and scenario[Scenario.SCRIPT]: self.script = self.get_script_path() elif "requests" in scenario: self.get_scenario( )['simulation'], self.script = self.__generate_script() else: msg = "There must be a script file or requests for its generation " msg += "to run Gatling tool (%s)" % self.execution.get('scenario') raise TaurusConfigError(msg) self.dir_prefix = 'gatling-%s' % id(self) self.reader = DataLogReader(self.engine.artifacts_dir, self.log, self.dir_prefix) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader)
def load(self, configs, callback=None): """ Load and merge JSON/YAML files into current dict :type callback: callable :type configs: list[str] """ self.log.debug("Configs: %s", configs) for config_file in configs: try: config = self.__read_file(config_file) except BaseException as exc: raise TaurusConfigError("Error when reading config file '%s': %s" % (config_file, exc)) self.merge(config) if callback is not None: callback(config_file)
def __prepare_reporters(self): """ Instantiate reporters, then prepare them in case they would like to interact """ reporting = self.config.get(Reporter.REP, []) for index, reporter in enumerate(reporting): reporter = ensure_is_dict(reporting, index, "module") msg = "reporter 'module' field isn't recognized: %s" cls = reporter.get('module', TaurusConfigError(msg % reporter)) instance = self.instantiate_module(cls) instance.parameters = reporter assert isinstance(instance, Reporter) self.reporters.append(instance) # prepare reporters for module in self.reporters: self.prepared.append(module) module.prepare()
def resolve_project(self, workspace, project_name): if isinstance(project_name, (int, float)): # project id project_id = int(project_name) self.log.debug("Treating project name as ID: %s", project_id) project = workspace.projects(ident=project_id).first() if not project: raise TaurusConfigError( "BlazeMeter project not found by ID: %s" % project_id) elif project_name: project = workspace.projects(name=project_name).first() else: project = None if not project: project = self._create_project_or_use_default( workspace, project_name) return project
def connect(self): exc = TaurusConfigError( 'Metric is required in Local monitoring client') metric_names = self.config.get('metrics', exc) bad_list = set(metric_names) - set(self.AVAILABLE_METRICS) if bad_list: self.log.warning('Wrong metrics found: %s', bad_list) good_list = set(metric_names) & set(self.AVAILABLE_METRICS) if not good_list: raise exc self.metrics = list(set(good_list)) self.monitor = LocalMonitor(self.log, self.metrics, self.engine) self.interval = dehumanize_time( self.config.get("interval", self.engine.check_interval))
def __lint_config(self): settings = self.engine.config.get(CLI.CLI_SETTINGS).get("linter") self.log.debug("Linting config") self.warn_on_unfamiliar_fields = settings.get("warn-on-unfamiliar-fields", True) config_copy = copy.deepcopy(self.engine.config) ignored_warnings = settings.get("ignored-warnings", []) self.linter = ConfigurationLinter(config_copy, ignored_warnings, self.log) self.linter.register_checkers() self.linter.lint() warnings = self.linter.get_warnings() for warning in warnings: self.log.warning(str(warning)) if settings.get("lint-and-exit", False): if warnings: raise TaurusConfigError("Errors were found in the configuration") else: raise NormalShutdown("Linting has finished, no errors were found")
def post_process(self): """ Get report data, generate xml report. """ super(JUnitXMLReporter, self).post_process() test_data_source = self.parameters.get("data-source", "sample-labels") if test_data_source == "sample-labels": if self.last_second: root_element = self.process_sample_labels() self.save_report(root_element) else: self.log.warning("No last second data to generate XUnit.xml") elif test_data_source == "pass-fail": root_element = self.process_pass_fail() self.save_report(root_element) else: raise TaurusConfigError("Unsupported data source: %s" % test_data_source)
def prepare(self): self.install_required_tools() scenario = self.get_scenario() self.exec_id = self.label self.script = self.get_script_path() if not self.script: if "requests" in scenario: self.script = self.__scenario_from_requests() else: msg = "There must be a script file or requests for its generation " msg += "to run Grinder tool (%s)" % self.execution.get( 'scenario') raise TaurusConfigError(msg) self.properties_file = self.engine.create_artifact( "grinder", ".properties") with open(self.properties_file, 'w') as fds: self.__write_base_props(fds) self.__write_scenario_props(fds, scenario) self.__write_bzt_props(fds) self.kpi_file = os.path.join(self.engine.artifacts_dir, self.exec_id + "-kpi.log") self.reader = DataLogReader(self.kpi_file, self.log) self.reader.report_by_url = self.settings.get("report-by-url", False) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader) # add logback configurations used by worker processes (logback-worker.xml) res_dir = os.path.join(get_full_path(__file__, step_up=2), 'resources') self.env.add_path({"CLASSPATH": res_dir}, finish=True) self.env.add_path( { "CLASSPATH": TaurusJavaHelper(self.engine.get_http_client()).tool_path }, finish=True) self.env.add_path({"CLASSPATH": self.settings.get("path", None)}, finish=True) self.cmd_line = ["java", "net.grinder.Grinder", self.properties_file]
def gen_setup_method(self): self.log.debug("Generating setUp test method") browsers = ["Firefox", "Chrome", "Ie", "Opera"] browser = self.scenario.get("browser", "Firefox") if browser not in browsers: raise TaurusConfigError("Unsupported browser name: %s" % browser) setup_method_def = self.gen_method_definition("setUp", ["self"]) if browser == 'Firefox': setup_method_def.append( self.gen_statement("profile = webdriver.FirefoxProfile()")) statement = "profile.set_preference('webdriver.log.file', %s)" % repr( self.wdlog) log_set = self.gen_statement(statement) setup_method_def.append(log_set) setup_method_def.append( self.gen_statement("self.driver = webdriver.Firefox(profile)")) elif browser == 'Chrome': statement = "self.driver = webdriver.Chrome(service_log_path=%s)" setup_method_def.append( self.gen_statement(statement % repr(self.wdlog))) else: setup_method_def.append( self.gen_statement("self.driver = webdriver.%s()" % browser)) scenario_timeout = self.scenario.get("timeout", None) if scenario_timeout is None: scenario_timeout = '30s' setup_method_def.append(self.gen_impl_wait(scenario_timeout)) if self.window_size: # FIXME: unused in fact statement = self.gen_statement( "self.driver.set_window_position(0, 0)") setup_method_def.append(statement) args = (self.window_size[0], self.window_size[1]) statement = self.gen_statement( "self.driver.set_window_size(%s, %s)" % args) setup_method_def.append(statement) else: pass # TODO: setup_method_def.append(self.gen_statement("self.driver.fullscreen()")) setup_method_def.append(self.gen_new_line(indent=0)) return setup_method_def
def __add_jsr_elements(children, req): """ :type children: etree.Element :type req: Request """ jsrs = req.config.get("jsr223", []) if not isinstance(jsrs, list): jsrs = [jsrs] for idx, _ in enumerate(jsrs): jsr = ensure_is_dict(jsrs, idx, default_key='script-text') lang = jsr.get("language", "groovy") script_file = jsr.get("script-file", None) script_text = jsr.get("script-text", None) if not script_file and not script_text: raise TaurusConfigError("jsr223 element must specify one of 'script-file' or 'script-text'") parameters = jsr.get("parameters", "") execute = jsr.get("execute", "after") children.append(JMX._get_jsr223_element(lang, script_file, parameters, execute, script_text)) children.append(etree.Element("hashTree"))
def prepare(self): """ Read aggregation options """ super(ConsolidatingAggregator, self).prepare() # make unique & sort percentiles = self.settings.get("percentiles", self.track_percentiles) percentiles = list(set(percentiles)) percentiles.sort() self.track_percentiles = percentiles self.settings['percentiles'] = percentiles self.ignored_labels = self.settings.get("ignore-labels", self.ignored_labels) self.generalize_labels = self.settings.get("generalize-labels", self.generalize_labels) self.min_buffer_len = dehumanize_time(self.settings.get("min-buffer-len", self.min_buffer_len)) max_buffer_len = self.settings.get("max-buffer-len", self.max_buffer_len) try: # for max_buffer_len == float('inf') self.max_buffer_len = dehumanize_time(max_buffer_len) except TaurusInternalException as exc: self.log.debug("Exception in dehumanize_time(%s)" % max_buffer_len) if str(exc).find('inf') != -1: self.max_buffer_len = max_buffer_len else: raise TaurusConfigError("Wrong 'max-buffer-len' value: %s" % max_buffer_len) self.buffer_multiplier = self.settings.get("buffer-multiplier", self.buffer_multiplier) percentile = self.settings.get("buffer-scale-choice", 0.5) count = len(self.track_percentiles) if count == 1: self.buffer_scale_idx = str(float(self.track_percentiles[0])) if count > 1: percentiles = [i / (count - 1.0) for i in range(count)] distances = [abs(percentile - percentiles[i]) for i in range(count)] index_position = distances.index(min(distances)) self.buffer_scale_idx = str(float(self.track_percentiles[index_position])) debug_str = 'Buffer scaling setup: percentile %s from %s selected' self.log.debug(debug_str, self.buffer_scale_idx, self.track_percentiles) self.rtimes_len = self.settings.get("rtimes-len", self.rtimes_len)
def prepare(self): super(ApiritifNoseExecutor, self).prepare() if 'executor' in self.execution.keys(): if self.execution['executor'] == 'nose': msg = "'nose' keyword is deprecated and will be removed soon. Please use 'apiritif' instead." self.log.warning(msg) self.script = self.get_script_path() if not self.script: if "requests" in self.get_scenario(): self.script = self.__tests_from_requests() else: raise TaurusConfigError("Nothing to test, no requests were provided in scenario") # todo: requred tools? # path to taurus dir. It's necessary for bzt usage inside tools/helpers self.env.add_path({"PYTHONPATH": get_full_path(BZT_DIR, step_up=1)}) self.reporting_setup() # no prefix/suffix because we don't fully control report file names
def _get_timer(req): think_time = req.get_think_time(full=True) if not think_time: return [] if not isinstance(think_time, list): # constant return JMX.get_constant_timer(delay=ProtocolHandler.safe_time(think_time)) mean = ProtocolHandler.safe_time(think_time[1]) dev = ProtocolHandler.safe_time(think_time[2]) if think_time[0] == "uniform": return JMX.get_uniform_timer(maximum=dev * 2, offset=mean - dev) elif think_time[0] == "gaussian": return JMX.get_gaussian_timer(dev=dev, offset=mean) elif think_time[0] == "poisson": return JMX.get_poisson_timer(lam=mean - dev, delay=dev) else: raise TaurusConfigError("Wrong timer type: %s" % think_time[0])
def _add_xpath_assertions(self, request, test_method): jpath_assertions = request.config.get("assert-xpath", []) for idx, assertion in enumerate(jpath_assertions): assertion = ensure_is_dict(jpath_assertions, idx, "xpath") exc = TaurusConfigError('XPath not found in assertion: %s' % assertion) query = assertion.get('xpath', exc) parser_type = 'html' if assertion.get('use-tolerant-parser', True) else 'xml' validate = assertion.get('validate-xml', False) method = "assert_not_xpath" if assertion.get( 'invert', False) else "assert_xpath" line = "response.{method}({query}, parser_type={parser_type}, validate={validate})".format( method=method, query=repr(query), validate=repr(validate), parser_type=repr(parser_type), ) test_method.append(self.gen_statement(line))
def _fix_filenames(self, old_names): # check for concurrent base names old_full_names = [self.engine.find_file(x) for x in old_names] rbases = [os.path.basename(get_full_path(rfile)) for rfile in old_full_names] rpaths = [get_full_path(rfile, step_up=1) for rfile in old_full_names] while rbases: base, path = rbases.pop(), rpaths.pop() if base in rbases: index = rbases.index(base) if path != rpaths[index]: msg = 'Resource "%s" occurs more than one time, rename to avoid data loss' raise TaurusConfigError(msg % base) old_full_names = self.__pack_dirs(old_full_names) new_base_names = [os.path.basename(f) for f in old_full_names] self.log.debug('Replace file names in config: %s with %s', old_names, new_base_names) replace_in_config(self.engine.config, old_names, new_base_names, log=self.log) old_full_names = list(set(old_full_names)) return old_full_names
def get_script_path(self, required=False, scenario=None): """ :type required: bool :type scenario: Scenario """ if scenario is None: scenario = self.get_scenario() if required: exc = TaurusConfigError("You must provide script for %s" % self) script = scenario.get(Scenario.SCRIPT, exc) else: script = scenario.get(Scenario.SCRIPT) if script: script = self.engine.find_file(script) scenario[Scenario.SCRIPT] = script return script
def gen_setupclass_method(self): self.log.debug("Generating setUp test method") browsers = ["Firefox", "Chrome", "Ie", "Opera"] browser = self.scenario.get("browser", "Firefox") if browser not in browsers: raise TaurusConfigError("Unsupported browser name: %s" % browser) setup_method_def = self.gen_decorator_statement('classmethod') setup_method_def.append( self.gen_method_definition("setUpClass", ["cls"])) if browser == 'Firefox': setup_method_def.append( self.gen_statement("profile = webdriver.FirefoxProfile()")) statement = "profile.set_preference('webdriver.log.file', %s)" % repr( self.wdlog) log_set = self.gen_statement(statement) setup_method_def.append(log_set) setup_method_def.append( self.gen_statement("cls.driver = webdriver.Firefox(profile)")) elif browser == 'Chrome': statement = "cls.driver = webdriver.Chrome(service_log_path=%s)" setup_method_def.append( self.gen_statement(statement % repr(self.wdlog))) else: setup_method_def.append( self.gen_statement("cls.driver = webdriver.%s()" % browser)) scenario_timeout = self.scenario.get("timeout", None) if scenario_timeout is None: scenario_timeout = '30s' setup_method_def.append( self.gen_impl_wait(scenario_timeout, target='cls')) if self.window_size: args = (self.window_size[0], self.window_size[1]) # to force tuple statement = self.gen_statement( "cls.driver.set_window_size(%s, %s)" % args) setup_method_def.append(statement) else: setup_method_def.append( self.gen_statement("cls.driver.maximize_window()")) setup_method_def.append(self.gen_new_line()) return setup_method_def
def prepare(self): self.install_required_tools() scenario = self.get_scenario() self.exec_id = self.label self.script = self.get_script_path() if self.script: self.script = os.path.abspath(self.engine.find_file(self.script)) elif "requests" in scenario: self.script = self.__scenario_from_requests() else: msg = "There must be a script file or requests for its generation " msg += "to run Grinder tool (%s)" % self.execution.get('scenario') raise TaurusConfigError(msg) self.properties_file = self.engine.create_artifact( "grinder", ".properties") with open(self.properties_file, 'w') as fds: self.__write_base_props(fds) self.__write_scenario_props(fds, scenario) self.__write_bzt_props(fds) self.kpi_file = os.path.join(self.engine.artifacts_dir, self.exec_id + "-kpi.log") self.reader = DataLogReader(self.kpi_file, self.log) self.reader.report_by_url = self.settings.get("report-by-url", False) if isinstance(self.engine.aggregator, ConsolidatingAggregator): self.engine.aggregator.add_underling(self.reader) # add logback configurations used by worker processes (logback-worker.xml) res_dir = os.path.join(get_full_path(__file__, step_up=2), 'resources') classpath = res_dir classpath += os.path.pathsep + os.path.join(res_dir, "grinder-logger-1.0.jar") path = self.settings.get("path", None) if path: classpath += os.path.pathsep + path self.cmd_line = ["java", "-classpath", classpath] self.cmd_line += ["net.grinder.Grinder", self.properties_file]
def __gen_assertion(self, task, assertion, is_first): subject = assertion.get("subject", Scenario.FIELD_BODY) values = [str(_assert) for _assert in assertion['contains']] if subject == 'body': content = 'response.content' elif subject == 'http-code': content = 'str(response.status_code)' else: raise TaurusConfigError('Wrong subject for Locust assertion: %s' % subject) if assertion.get('not', False): attr_not = '' func_name = 'any' else: attr_not = ' not' func_name = 'all' if assertion.get("regexp", True): expression = 'findall(compile(str(val)), %(content)s)' % { 'content': content } else: expression = 'str(val) in %s' % content statement = 'if%(not)s %(func)s(%(expression)s for val in %(values)s):' statement = statement % { 'not': attr_not, 'func': func_name, 'expression': expression, 'values': values } if not is_first: statement = 'el' + statement task.append(self.gen_statement(statement, indent=12)) statement = 'response.failure("%(values)s%(not)s found in %(subject)s")' statement = statement % { 'values': values, 'not': attr_not, 'subject': subject } task.append(self.gen_statement(statement, indent=16))
def __init__(self, parent_log, label, config, engine): super(GraphiteClient, self).__init__(parent_log, engine) self.config = config exc = TaurusConfigError('Graphite client requires address parameter') self.address = self.config.get("address", exc) # interval for client interval = self.config.get('interval', None) if not interval: interval = '5s' self.interval = int(dehumanize_time(interval)) self.url = self._get_url() if label: self.host_label = label else: self.host_label = self.address self.timeout = int(dehumanize_time(self.config.get('timeout', '5s'))) self._cached_data = None
def __configure(self, configs): if self.options.no_system_configs is None: self.options.no_system_configs = False load_hidden_configs = not self.options.no_system_configs if load_hidden_configs: bzt_rc = os.path.expanduser(os.path.join('~', ".bzt-rc")) if os.path.exists(bzt_rc): self.log.debug("Using personal config: %s" % bzt_rc) else: self.log.debug("Adding personal config: %s", bzt_rc) self.log.info("No personal config found, creating one at %s", bzt_rc) shutil.copy(os.path.join(RESOURCES_DIR, 'base-bzt-rc.yml'), bzt_rc) configs.insert(0, bzt_rc) self.log.info("Starting with configs: %s", configs) merged_config = self.engine.configure( configs, not self.options.no_system_configs) # apply aliases for alias in self.options.aliases: cli_aliases = self.engine.config.get('cli-aliases') keys = sorted(cli_aliases.keys()) err = TaurusConfigError( "'%s' not found in aliases. Available aliases are: %s" % (alias, ", ".join(keys))) self.engine.config.merge(cli_aliases.get(alias, err)) if self.options.option: overrider = ConfigOverrider(self.log) overrider.apply_overrides(self.options.option, self.engine.config) if self.__is_verbose(): CLI.console_handler.setLevel(logging.DEBUG) self.engine.create_artifacts_dir(configs, merged_config) self.engine.default_cwd = os.getcwd() self.engine.set_pythonpath() self.engine.eval_env( ) # yacky, I don't like having it here, but how to apply it after aliases and artif dir?
def prepare(self): """ Read aggregation options """ super(ConsolidatingAggregator, self).prepare() # make unique & sort self.track_percentiles = self.settings.get("percentiles", self.track_percentiles) self.track_percentiles = list(set(self.track_percentiles)) self.track_percentiles.sort() self.settings["percentiles"] = self.track_percentiles self.extend_aggregation = self.settings.get('extend-aggregation') self.ignored_labels = self.settings.get("ignore-labels", self.ignored_labels) self.generalize_labels = self.settings.get("generalize-labels", self.generalize_labels) self.min_buffer_len = dehumanize_time(self.settings.get("min-buffer-len", self.min_buffer_len)) max_buffer_len = self.settings.get("max-buffer-len", self.max_buffer_len) try: self.max_buffer_len = dehumanize_time(max_buffer_len) except TaurusInternalException as exc: self.log.debug("Exception in dehumanize_time(%s): %s", max_buffer_len, exc) raise TaurusConfigError("Wrong 'max-buffer-len' value: %s" % max_buffer_len) self.buffer_multiplier = self.settings.get("buffer-multiplier", self.buffer_multiplier) count = len(self.track_percentiles) if count == 1: self.buffer_scale_idx = str(float(self.track_percentiles[0])) if count > 1: percentile = self.settings.get("buffer-scale-choice", 0.5) percentiles = [i / (count - 1.0) for i in range(count)] distances = [abs(percentile - percentiles[i]) for i in range(count)] index_position = distances.index(min(distances)) self.buffer_scale_idx = str(float(self.track_percentiles[index_position])) debug_str = 'Buffer scaling setup: percentile %s from %s selected' self.log.debug(debug_str, self.buffer_scale_idx, self.track_percentiles) self.histogram_max = dehumanize_time(self.settings.get("histogram-initial", self.histogram_max)) self.max_error_count = self.settings.get("max-error-variety", self.max_error_count)