Skip to content

Commit 264fb8c

Browse files
authored
Fix load test checks (#9885)
1 parent d26c822 commit 264fb8c

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

ydb/tests/olap/lib/allure_utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
def allure_test_description(
1010
suite: str,
1111
test: str,
12+
start_time: float,
13+
end_time: float,
1214
addition_table_strings: dict[str, any] = {},
1315
attachments: tuple[str, str, allure.attachment_type] = [],
14-
refference_set: str = ''
16+
refference_set: str = '',
1517
):
1618
def _pretty_str(s):
1719
return ' '.join(s.split('_')).capitalize()
@@ -33,7 +35,7 @@ def _pretty_str(s):
3335
'table_path': YdbCluster.tables_path,
3436
'monitoring': (
3537
f"<a target='_blank' href='https://monitoring.yandex-team.ru/projects/kikimr/dashboards/mone0310v4dbc6kui89v?"
36-
f"p.cluster={monitoring_cluster}&p.database=/{test_info['database']}'>link</a>"
38+
f"p.cluster={monitoring_cluster}&p.database=/{test_info['database']}&from={int(start_time * 1000)}&to={int(end_time * 1000)}'>link</a>"
3739
),
3840
'coredumps': f"<a target='_blank' href='{core_link}'>link</a>",
3941
'db_admin': (

ydb/tests/olap/lib/ydb_cli.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from ydb.tests.olap.lib.ydb_cluster import YdbCluster
77
from ydb.tests.olap.lib.utils import get_external_param
88
from enum import StrEnum
9+
from time import time
10+
from types import TracebackType
911

1012

1113
class WorkloadType(StrEnum):
@@ -37,7 +39,7 @@ class WorkloadRunResult:
3739
def __init__(
3840
self, stats: dict[str, dict[str, any]] = {}, query_out: Optional[str] = None, stdout: Optional[str] = None, stderr: Optional[str] = None,
3941
error_message: Optional[str] = None, plans: Optional[list[YdbCliHelper.QueryPlan]] = None,
40-
errors_by_iter: Optional[dict[int, str]] = None, explain_plan: Optional[YdbCliHelper.QueryPlan] = None
42+
errors_by_iter: Optional[dict[int, str]] = None, explain_plan: Optional[YdbCliHelper.QueryPlan] = None, traceback: Optional[TracebackType] = None
4143
) -> None:
4244
self.stats = stats
4345
self.query_out = query_out if str != '' else None
@@ -48,6 +50,7 @@ def __init__(
4850
self.plans = plans
4951
self.explain_plan = explain_plan
5052
self.errors_by_iter = errors_by_iter
53+
self.traceback = traceback
5154

5255
@staticmethod
5356
def workload_run(type: WorkloadType, path: str, query_num: int, iterations: int = 5,
@@ -95,13 +98,22 @@ def _load_plans(plan_path: str, name: str) -> YdbCliHelper.QueryPlan:
9598
result.svg = f.read()
9699
return result
97100

101+
def _get_nodes_info() -> dict[str, dict[str, int]]:
102+
nodes, _ = YdbCluster.get_cluster_nodes()
103+
return {
104+
n['SystemState']['Host']: {
105+
'start_time': int(n['SystemState'].get('StartTime', int(time()) * 1000) / 1000)
106+
}
107+
for n in nodes
108+
}
109+
98110
errors_by_iter = {}
99111
try:
100112
wait_error = YdbCluster.wait_ydb_alive(300, path)
101113
if wait_error is not None:
102114
return YdbCliHelper.WorkloadRunResult(error_message=f'Ydb cluster is dead: {wait_error}')
103115

104-
cluster_start_time = YdbCluster.get_cluster_info().get('max_start_time', 0)
116+
nodes_info = _get_nodes_info()
105117

106118
json_path = yatest.common.work_path(f'q{query_num}.json')
107119
qout_path = yatest.common.work_path(f'q{query_num}.out')
@@ -132,8 +144,23 @@ def _load_plans(plan_path: str, name: str) -> YdbCliHelper.QueryPlan:
132144
err = f'Invalid return code: {exec.returncode} instesd 0.'
133145
except (yatest.common.process.TimeoutError, yatest.common.process.ExecutionTimeoutError):
134146
err = f'Timeout {timeout}s expeared.'
135-
if YdbCluster.get_cluster_info().get('max_start_time', 0) != cluster_start_time:
136-
err = ('' if err is None else f'{err}\n\n') + 'Some nodes were restart'
147+
148+
node_errors = []
149+
for node, info in _get_nodes_info().items():
150+
if node in nodes_info:
151+
if info['start_time'] > nodes_info[node]['start_time']:
152+
node_errors.append(f'Node {node} was restarted')
153+
nodes_info[node]['processed'] = True
154+
for node, info in nodes_info.items():
155+
if not info.get('processed', False):
156+
node_errors.append(f'Node {node} is down')
157+
if len(node_errors) > 0:
158+
if err is None:
159+
err = ''
160+
else:
161+
err += '\n\n'
162+
err += '\n'.join(node_errors)
163+
137164
stats = {}
138165
if (os.path.exists(json_path)):
139166
with open(json_path, 'r') as r:
@@ -162,4 +189,4 @@ def _load_plans(plan_path: str, name: str) -> YdbCliHelper.QueryPlan:
162189
errors_by_iter=errors_by_iter
163190
)
164191
except BaseException as e:
165-
return YdbCliHelper.WorkloadRunResult(error_message=str(e))
192+
return YdbCliHelper.WorkloadRunResult(error_message=str(e), traceback=e.__traceback__)

ydb/tests/olap/lib/ydb_cluster.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def _get_service_url(cls):
2929
return f'http://{host}:{port}'
3030

3131
@classmethod
32-
def _get_cluster_nodes(cls, path=None):
32+
def get_cluster_nodes(cls, path=None):
3333
try:
3434
url = f'{cls._get_service_url()}/viewer/json/nodes?'
3535
if path is not None:
@@ -52,11 +52,9 @@ def get_cluster_info(cls):
5252
version = ''
5353
cluster_name = ''
5454
nodes_wilcard = ''
55-
max_start_time = 0
56-
nodes, node_count = cls._get_cluster_nodes()
55+
nodes, node_count = cls.get_cluster_nodes()
5756
for node in nodes:
5857
n = node.get('SystemState', {})
59-
max_start_time = max(max_start_time, int(n.get('StartTime', 0)))
6058
cluster_name = n.get('ClusterName', cluster_name)
6159
version = n.get('Version', version)
6260
for tenant in n.get('Tenants', []):
@@ -69,7 +67,6 @@ def get_cluster_info(cls):
6967
'name': cluster_name,
7068
'nodes_wilcard': nodes_wilcard,
7169
'service_url': cls._get_service_url(),
72-
'max_start_time': max_start_time,
7370
}
7471
return deepcopy(cls._cluster_info)
7572

@@ -184,7 +181,7 @@ def _check_node(n):
184181

185182
errors = []
186183
try:
187-
nodes, node_count = cls._get_cluster_nodes()
184+
nodes, node_count = cls.get_cluster_nodes()
188185
if node_count == 0:
189186
errors.append('nodes_count == 0')
190187
if len(nodes) < node_count:
@@ -216,7 +213,7 @@ def _check_node(n):
216213
for path in balanced_paths:
217214
paths_to_balance += cls._get_tables(path)
218215
for p in paths_to_balance:
219-
table_nodes, _ = cls._get_cluster_nodes(p)
216+
table_nodes, _ = cls.get_cluster_nodes(p)
220217
min = None
221218
max = None
222219
for tn in table_nodes:

ydb/tests/olap/load/conftest.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ def _attach_plans(plan: YdbCliHelper.QueryPlan) -> None:
4040
allure.attach(plan.svg, 'Plan svg', attachment_type=allure.attachment_type.SVG)
4141

4242
test = f'Query{query_num:02d}'
43-
allure_test_description(self.suite, test, refference_set=self.refference)
4443
allure_listener = next(filter(lambda x: isinstance(x, AllureListener), plugin_manager.get_plugin_manager().get_plugins()))
4544
allure_test_result = allure_listener.allure_logger.get_test(None)
4645
query_num_param = next(filter(lambda x: x.name == 'query_num', allure_test_result.parameters), None)
4746
if query_num_param:
4847
query_num_param.mode = allure.parameter_mode.HIDDEN.value
49-
48+
start_time = time()
5049
result = YdbCliHelper.workload_run(
5150
path=path, query_num=query_num, iterations=self.iterations, type=self.workload_type, timeout=self.timeout
5251
)
52+
allure_test_description(self.suite, test, refference_set=self.refference, start_time=start_time, end_time=time())
5353
stats = result.stats.get(test)
5454
if stats is not None:
5555
allure.attach(json.dumps(stats, indent=2), 'Stats', attachment_type=allure.attachment_type.JSON)
@@ -103,7 +103,7 @@ def _attach_plans(plan: YdbCliHelper.QueryPlan) -> None:
103103
kind='Load',
104104
suite=self.suite,
105105
test=test,
106-
timestamp=time(),
106+
timestamp=start_time,
107107
is_successful=success,
108108
min_duration=_get_duraton(stats, 'Min'),
109109
max_duration=_get_duraton(stats, 'Max'),
@@ -112,4 +112,7 @@ def _attach_plans(plan: YdbCliHelper.QueryPlan) -> None:
112112
statistics=stats,
113113
)
114114
if not success:
115-
pytest.fail(error_message)
115+
exc = pytest.fail.Exception(error_message)
116+
if result.traceback is not None:
117+
exc = exc.with_traceback(result.traceback)
118+
raise exc

ydb/tests/olap/scenario/conftest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ def teardown_class(cls):
2828
ScenarioTestHelper(None).remove_path(cls.get_suite_name())
2929

3030
def test(self, ctx: TestContext):
31-
allure_test_description(ctx.suite, ctx.test)
3231
start_time = time.time()
3332
try:
3433
ctx.executable(self, ctx)
@@ -41,6 +40,7 @@ def test(self, ctx: TestContext):
4140
is_successful=True,
4241
)
4342
except pytest.skip.Exception:
43+
allure_test_description(ctx.suite, ctx.test, start_time=start_time, end_time=time.time())
4444
raise
4545
except BaseException:
4646
ResultsProcessor.upload_results(
@@ -51,7 +51,9 @@ def test(self, ctx: TestContext):
5151
duration=time.time() - start_time,
5252
is_successful=False,
5353
)
54+
allure_test_description(ctx.suite, ctx.test, start_time=start_time, end_time=time.time())
5455
raise
56+
allure_test_description(ctx.suite, ctx.test, start_time=start_time, end_time=time.time())
5557

5658

5759
def pytest_generate_tests(metafunc):

0 commit comments

Comments
 (0)