Add prometheus load parameters #185
3 changed files with 67 additions and 13 deletions
|
@ -61,7 +61,7 @@ class K6:
|
||||||
self._k6_dir: str = k6_dir
|
self._k6_dir: str = k6_dir
|
||||||
|
|
||||||
command = (
|
command = (
|
||||||
f"{self._k6_dir}/k6 run {self._generate_env_variables()} "
|
f"{self._generate_env_variables()}{self._k6_dir}/k6 run {self._generate_k6_variables()} "
|
||||||
f"{self._k6_dir}/scenarios/{self.load_params.scenario.value}.js"
|
f"{self._k6_dir}/scenarios/{self.load_params.scenario.value}.js"
|
||||||
)
|
)
|
||||||
user = STORAGE_USER_NAME if self.load_params.scenario == LoadScenario.LOCAL else None
|
user = STORAGE_USER_NAME if self.load_params.scenario == LoadScenario.LOCAL else None
|
||||||
|
@ -75,12 +75,12 @@ class K6:
|
||||||
def _get_fill_percents(self):
|
def _get_fill_percents(self):
|
||||||
fill_percents = self.shell.exec("df -H --output=source,pcent,target | grep frostfs").stdout.split("\n")
|
fill_percents = self.shell.exec("df -H --output=source,pcent,target | grep frostfs").stdout.split("\n")
|
||||||
return [line.split() for line in fill_percents][:-1]
|
return [line.split() for line in fill_percents][:-1]
|
||||||
|
|
||||||
def check_fill_percent(self):
|
def check_fill_percent(self):
|
||||||
fill_percents = self._get_fill_percents()
|
fill_percents = self._get_fill_percents()
|
||||||
percent_mean = 0
|
percent_mean = 0
|
||||||
for line in fill_percents:
|
for line in fill_percents:
|
||||||
percent_mean += float(line[1].split('%')[0])
|
percent_mean += float(line[1].split("%")[0])
|
||||||
percent_mean = percent_mean / len(fill_percents)
|
percent_mean = percent_mean / len(fill_percents)
|
||||||
logger.info(f"{self.loader.ip} mean fill percent is {percent_mean}")
|
logger.info(f"{self.loader.ip} mean fill percent is {percent_mean}")
|
||||||
return percent_mean >= self.load_params.fill_percent
|
return percent_mean >= self.load_params.fill_percent
|
||||||
|
@ -125,9 +125,9 @@ class K6:
|
||||||
self.preset_output = result.stdout.strip("\n")
|
self.preset_output = result.stdout.strip("\n")
|
||||||
return self.preset_output
|
return self.preset_output
|
||||||
|
|
||||||
@reporter.step("Generate K6 command")
|
@reporter.step("Generate K6 variables")
|
||||||
def _generate_env_variables(self) -> str:
|
def _generate_k6_variables(self) -> str:
|
||||||
env_vars = self.load_params.get_env_vars()
|
env_vars = self.load_params.get_k6_vars()
|
||||||
|
|
||||||
env_vars[f"{self.load_params.load_type.value.upper()}_ENDPOINTS"] = ",".join(self.endpoints)
|
env_vars[f"{self.load_params.load_type.value.upper()}_ENDPOINTS"] = ",".join(self.endpoints)
|
||||||
env_vars["SUMMARY_JSON"] = self.summary_json
|
env_vars["SUMMARY_JSON"] = self.summary_json
|
||||||
|
@ -135,6 +135,14 @@ class K6:
|
||||||
reporter.attach("\n".join(f"{param}: {value}" for param, value in env_vars.items()), "K6 ENV variables")
|
reporter.attach("\n".join(f"{param}: {value}" for param, value in env_vars.items()), "K6 ENV variables")
|
||||||
return " ".join([f"-e {param}='{value}'" for param, value in env_vars.items() if value is not None])
|
return " ".join([f"-e {param}='{value}'" for param, value in env_vars.items() if value is not None])
|
||||||
|
|
||||||
|
@reporter.step("Generate env variables")
|
||||||
|
def _generate_env_variables(self) -> str:
|
||||||
|
env_vars = self.load_params.get_env_vars()
|
||||||
|
if not env_vars:
|
||||||
|
return ""
|
||||||
|
reporter.attach("\n".join(f"{param}: {value}" for param, value in env_vars.items()), "ENV variables")
|
||||||
|
return " ".join([f"{param}='{value}'" for param, value in env_vars.items() if value is not None]) + " "
|
||||||
|
|
||||||
def get_start_time(self) -> datetime:
|
def get_start_time(self) -> datetime:
|
||||||
return datetime.fromtimestamp(self._k6_process.start_time())
|
return datetime.fromtimestamp(self._k6_process.start_time())
|
||||||
|
|
||||||
|
@ -188,23 +196,25 @@ class K6:
|
||||||
wait_interval = min_wait_interval
|
wait_interval = min_wait_interval
|
||||||
if self._k6_process is None:
|
if self._k6_process is None:
|
||||||
assert "No k6 instances were executed"
|
assert "No k6 instances were executed"
|
||||||
|
|
||||||
while timeout > 0:
|
while timeout > 0:
|
||||||
if not self.load_params.fill_percent is None:
|
if not self.load_params.fill_percent is None:
|
||||||
with reporter.step(f"Check the percentage of filling of all data disks on the node"):
|
with reporter.step(f"Check the percentage of filling of all data disks on the node"):
|
||||||
if self.check_fill_percent():
|
if self.check_fill_percent():
|
||||||
logger.info(f"Stopping load on because disks is filled more then {self.load_params.fill_percent}%")
|
logger.info(
|
||||||
|
f"Stopping load on because disks is filled more then {self.load_params.fill_percent}%"
|
||||||
|
)
|
||||||
event.set()
|
event.set()
|
||||||
self.stop()
|
self.stop()
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.is_set():
|
if event.is_set():
|
||||||
self.stop()
|
self.stop()
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self._k6_process.running():
|
if not self._k6_process.running():
|
||||||
return
|
return
|
||||||
|
|
||||||
remaining_time_hours = f"{timeout//3600}h" if timeout // 3600 != 0 else ""
|
remaining_time_hours = f"{timeout//3600}h" if timeout // 3600 != 0 else ""
|
||||||
remaining_time_minutes = f"{timeout//60%60}m" if timeout // 60 % 60 != 0 else ""
|
remaining_time_minutes = f"{timeout//60%60}m" if timeout // 60 % 60 != 0 else ""
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
|
@ -94,16 +94,18 @@ def metadata_field(
|
||||||
string_repr: Optional[bool] = True,
|
string_repr: Optional[bool] = True,
|
||||||
distributed: Optional[bool] = False,
|
distributed: Optional[bool] = False,
|
||||||
formatter: Optional[Callable] = None,
|
formatter: Optional[Callable] = None,
|
||||||
|
env_variable: Optional[str] = None,
|
||||||
):
|
):
|
||||||
return field(
|
return field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"applicable_scenarios": applicable_scenarios,
|
"applicable_scenarios": applicable_scenarios,
|
||||||
"preset_argument": preset_param,
|
"preset_argument": preset_param,
|
||||||
"env_variable": scenario_variable,
|
"scenario_variable": scenario_variable,
|
||||||
"string_repr": string_repr,
|
"string_repr": string_repr,
|
||||||
"distributed": distributed,
|
"distributed": distributed,
|
||||||
"formatter": formatter,
|
"formatter": formatter,
|
||||||
|
"env_variable": env_variable,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,6 +174,20 @@ class Preset:
|
||||||
local: Optional[bool] = metadata_field(grpc_preset_scenarios, "local", None, False)
|
local: Optional[bool] = metadata_field(grpc_preset_scenarios, "local", None, False)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PrometheusParams:
|
||||||
|
# Prometheus server URL
|
||||||
|
server_url: Optional[str] = metadata_field(
|
||||||
|
all_load_scenarios, env_variable="K6_PROMETHEUS_RW_SERVER_URL", string_repr=False
|
||||||
|
)
|
||||||
|
# Prometheus trend stats
|
||||||
|
trend_stats: Optional[str] = metadata_field(
|
||||||
|
all_load_scenarios, env_variable="K6_PROMETHEUS_RW_TREND_STATS", string_repr=False
|
||||||
|
)
|
||||||
|
# Additional tags
|
||||||
|
metrics_tags: Optional[str] = metadata_field(all_load_scenarios, None, "METRIC_TAGS", False)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LoadParams:
|
class LoadParams:
|
||||||
# ------- CONTROL PARAMS -------
|
# ------- CONTROL PARAMS -------
|
||||||
|
@ -223,6 +239,10 @@ class LoadParams:
|
||||||
fill_percent: Optional[float] = None
|
fill_percent: Optional[float] = None
|
||||||
# if set, the payload is generated on the fly and is not read into memory fully.
|
# if set, the payload is generated on the fly and is not read into memory fully.
|
||||||
streaming: Optional[int] = metadata_field(all_load_scenarios, None, "STREAMING", False)
|
streaming: Optional[int] = metadata_field(all_load_scenarios, None, "STREAMING", False)
|
||||||
|
# Output format
|
||||||
|
output: Optional[str] = metadata_field(all_load_scenarios, None, "K6_OUT", False)
|
||||||
|
# Prometheus params
|
||||||
|
prometheus: Optional[PrometheusParams] = None
|
||||||
|
|
||||||
# ------- COMMON SCENARIO PARAMS -------
|
# ------- COMMON SCENARIO PARAMS -------
|
||||||
# Load time is the maximum duration for k6 to give load. Default is the BACKGROUND_LOAD_DEFAULT_TIME value.
|
# Load time is the maximum duration for k6 to give load. Default is the BACKGROUND_LOAD_DEFAULT_TIME value.
|
||||||
|
@ -339,6 +359,17 @@ class LoadParams:
|
||||||
if self.preset:
|
if self.preset:
|
||||||
self.preset.pregen_json = os.path.join(self.working_dir, f"{load_id}_prepare.json")
|
self.preset.pregen_json = os.path.join(self.working_dir, f"{load_id}_prepare.json")
|
||||||
|
|
||||||
|
def get_k6_vars(self):
|
||||||
|
env_vars = {
|
||||||
|
meta_field.metadata["scenario_variable"]: meta_field.value
|
||||||
|
for meta_field in self._get_meta_fields(self)
|
||||||
|
if self.scenario in meta_field.metadata["applicable_scenarios"]
|
||||||
|
and meta_field.metadata["scenario_variable"]
|
||||||
|
and meta_field.value is not None
|
||||||
|
}
|
||||||
|
|
||||||
|
return env_vars
|
||||||
|
|
||||||
def get_env_vars(self):
|
def get_env_vars(self):
|
||||||
env_vars = {
|
env_vars = {
|
||||||
meta_field.metadata["env_variable"]: meta_field.value
|
meta_field.metadata["env_variable"]: meta_field.value
|
||||||
|
|
|
@ -157,6 +157,7 @@ class TestLoadConfig:
|
||||||
"DELETERS": 8,
|
"DELETERS": 8,
|
||||||
"READ_AGE": 8,
|
"READ_AGE": 8,
|
||||||
"STREAMING": 9,
|
"STREAMING": 9,
|
||||||
|
"K6_OUT": "output",
|
||||||
"PREGEN_JSON": "pregen_json",
|
"PREGEN_JSON": "pregen_json",
|
||||||
"PREPARE_LOCALLY": True,
|
"PREPARE_LOCALLY": True,
|
||||||
}
|
}
|
||||||
|
@ -181,6 +182,7 @@ class TestLoadConfig:
|
||||||
expected_env_vars = {
|
expected_env_vars = {
|
||||||
"DURATION": 9,
|
"DURATION": 9,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
|
"K6_OUT": "output",
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
"K6_SETUP_TIMEOUT": "setup_timeout",
|
"K6_SETUP_TIMEOUT": "setup_timeout",
|
||||||
|
@ -221,6 +223,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 9,
|
"DURATION": 9,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
|
"K6_OUT": "output",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
"K6_SETUP_TIMEOUT": "setup_timeout",
|
"K6_SETUP_TIMEOUT": "setup_timeout",
|
||||||
"WRITERS": 7,
|
"WRITERS": 7,
|
||||||
|
@ -254,6 +257,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 183900,
|
"DURATION": 183900,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
|
"K6_OUT": "output",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
"K6_SETUP_TIMEOUT": "setup_timeout",
|
"K6_SETUP_TIMEOUT": "setup_timeout",
|
||||||
"NO_VERIFY_SSL": True,
|
"NO_VERIFY_SSL": True,
|
||||||
|
@ -293,6 +297,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 9,
|
"DURATION": 9,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
|
"K6_OUT": "output",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
"K6_SETUP_TIMEOUT": "setup_timeout",
|
"K6_SETUP_TIMEOUT": "setup_timeout",
|
||||||
"NO_VERIFY_SSL": True,
|
"NO_VERIFY_SSL": True,
|
||||||
|
@ -332,6 +337,7 @@ class TestLoadConfig:
|
||||||
expected_env_vars = {
|
expected_env_vars = {
|
||||||
"DURATION": 9,
|
"DURATION": 9,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
|
"K6_OUT": "output",
|
||||||
"NO_VERIFY_SSL": True,
|
"NO_VERIFY_SSL": True,
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
|
@ -365,6 +371,7 @@ class TestLoadConfig:
|
||||||
"CONFIG_FILE": "config_file",
|
"CONFIG_FILE": "config_file",
|
||||||
"DURATION": 9,
|
"DURATION": 9,
|
||||||
"WRITE_OBJ_SIZE": 11,
|
"WRITE_OBJ_SIZE": 11,
|
||||||
|
"K6_OUT": "output",
|
||||||
"REGISTRY_FILE": "registry_file",
|
"REGISTRY_FILE": "registry_file",
|
||||||
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
|
||||||
"K6_SETUP_TIMEOUT": "setup_timeout",
|
"K6_SETUP_TIMEOUT": "setup_timeout",
|
||||||
|
@ -419,6 +426,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 0,
|
"DURATION": 0,
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"WRITERS": 0,
|
"WRITERS": 0,
|
||||||
|
@ -449,6 +457,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 0,
|
"DURATION": 0,
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"MAX_WRITERS": 0,
|
"MAX_WRITERS": 0,
|
||||||
|
@ -486,6 +495,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 0,
|
"DURATION": 0,
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"WRITERS": 0,
|
"WRITERS": 0,
|
||||||
|
@ -516,6 +526,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 0,
|
"DURATION": 0,
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"NO_VERIFY_SSL": False,
|
"NO_VERIFY_SSL": False,
|
||||||
|
@ -554,6 +565,7 @@ class TestLoadConfig:
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"NO_VERIFY_SSL": False,
|
"NO_VERIFY_SSL": False,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"WRITERS": 0,
|
"WRITERS": 0,
|
||||||
|
@ -584,6 +596,7 @@ class TestLoadConfig:
|
||||||
"DURATION": 0,
|
"DURATION": 0,
|
||||||
"WRITE_OBJ_SIZE": 0,
|
"WRITE_OBJ_SIZE": 0,
|
||||||
"REGISTRY_FILE": "",
|
"REGISTRY_FILE": "",
|
||||||
|
"K6_OUT": "",
|
||||||
"K6_MIN_ITERATION_DURATION": "",
|
"K6_MIN_ITERATION_DURATION": "",
|
||||||
"K6_SETUP_TIMEOUT": "",
|
"K6_SETUP_TIMEOUT": "",
|
||||||
"WRITERS": 0,
|
"WRITERS": 0,
|
||||||
|
@ -655,7 +668,7 @@ class TestLoadConfig:
|
||||||
assert sorted(preset_parameters) == sorted(expected_preset_args)
|
assert sorted(preset_parameters) == sorted(expected_preset_args)
|
||||||
|
|
||||||
def _check_env_vars(self, load_params: LoadParams, expected_env_vars: dict[str, str]):
|
def _check_env_vars(self, load_params: LoadParams, expected_env_vars: dict[str, str]):
|
||||||
env_vars = load_params.get_env_vars()
|
env_vars = load_params.get_k6_vars()
|
||||||
assert env_vars == expected_env_vars
|
assert env_vars == expected_env_vars
|
||||||
|
|
||||||
def _check_all_values_none(self, dataclass, skip_fields=None):
|
def _check_all_values_none(self, dataclass, skip_fields=None):
|
||||||
|
|
Loading…
Reference in a new issue